Merge "DHCP should be disabled on external subnet"
diff --git a/HACKING.rst b/HACKING.rst
index 607682b..81a7c2c 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -13,6 +13,7 @@
- [T104] Scenario tests require a services decorator
- [T105] Tests cannot use setUpClass/tearDownClass
- [T106] vim configuration should not be kept in source files.
+- [T107] Check that a service tag isn't in the module path
- [N322] Method's default argument shouldn't be mutable
Test Data/Configuration
diff --git a/README.rst b/README.rst
index 5284bbf..7af0025 100644
--- a/README.rst
+++ b/README.rst
@@ -124,14 +124,14 @@
Python 2.6
----------
-Tempest can be run with Python 2.6 however the unit tests and the gate
-currently only run with Python 2.7, so there are no guarantees about the state
-of tempest when running with Python 2.6. Additionally, to enable testr to work
-with tempest using python 2.6 the discover module from the unittest-ext
-project has to be patched to switch the unittest.TestSuite to use
-unittest2.TestSuite instead. See:
-
-https://code.google.com/p/unittest-ext/issues/detail?id=79
+Starting in the kilo release the OpenStack services dropped all support for
+python 2.6. This change has been mirrored in tempest, starting after the
+tempest-2 tag. This means that proposed changes to tempest which only fix
+python 2.6 compatibility will be rejected, and moving forward more features not
+present in python 2.6 will be used. If you're running you're OpenStack services
+on an earlier release with python 2.6 you can easily run tempest against it
+from a remote system running python 2.7. (or deploy a cloud guest in your cloud
+that has python 2.7)
Branchless Tempest Considerations
---------------------------------
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
new file mode 100644
index 0000000..08f37cc
--- /dev/null
+++ b/doc/source/configuration.rst
@@ -0,0 +1,115 @@
+Tempest Configuration Guide
+===========================
+
+Auth/Credentials
+----------------
+
+Tempest currently has 2 different ways in configuration to provide credentials
+to use when running tempest. One is a traditional set of configuration options
+in the tempest.conf file. These options are in the identity section and let you
+specify a regular user, a global admin user, and a alternate user set of
+credentials. (which consist of a username, password, and project/tenant name)
+These options should be clearly labelled in the sample config file in the
+identity section.
+
+The other method to provide credentials is using the accounts.yaml file. This
+file is used to specify an arbitrary number of users available to run tests
+with. You can specify the location of the file in the
+auth section in the tempest.conf file. To see the specific format used in
+the file please refer to the accounts.yaml.sample file included in tempest.
+Currently users that are specified in the accounts.yaml file are assumed to
+have the same set of roles which can be used for executing all the tests you
+are running. This will be addressed in the future, but is a current limitation.
+Eventually the config options for providing credentials to tempest will be
+deprecated and removed in favor of the accounts.yaml file.
+
+Credential Provider Mechanisms
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Tempest currently also has 3 different internal methods for providing
+authentication to tests. Tenant isolation, locking test accounts, and
+non-locking test accounts. Depending on which one is in use the configuration
+of tempest is slightly different.
+
+Tenant Isolation
+""""""""""""""""
+Tenant isolation was originally create to enable running tempest in parallel.
+For each test class it creates a unique set of user credentials to use for the
+tests in the class. It can create up to 3 sets of username, password, and
+tenant/project names for a primary user, an admin user, and an alternate user.
+To enable and use tenant isolation you only need to configure 2 things:
+
+ #. A set of admin credentials with permissions to create users and
+ tenants/projects. This is specified in the identity section with the
+ admin_username, admin_tenant_name, and admin_password options
+ #. To enable tenant_isolation in the auth section with the
+ allow_tenant_isolation option.
+
+
+Locking Test Accounts
+"""""""""""""""""""""
+For a long time using tenant isolation was the only method available if you
+wanted to enable parallel execution of tempest tests. However this was
+insufficient for certain use cases because of the admin credentials requirement
+to create the credential sets on demand. To get around that the accounts.yaml
+file was introduced and with that a new internal credential provider to enable
+using the list of credentials instead of creating them on demand. With locking
+test accounts each test class will reserve a set of credentials from the
+accounts.yaml before executing any of its tests so that each class is isolated
+like in tenant isolation.
+
+Currently, this mechanism has some limitations, first only non-admin users with
+the same role set can be used at one time. The second limitation is around
+networking, locking test accounts will only work with a single flat network as
+the default for each tenant/project. If another network configuration is used
+in your cloud you might face unexpected failures.
+
+To enable and use locking test accounts you need do a few things:
+
+ #. Enable the locking test account provider with the
+ locking_credentials_provider option in the auth section
+ #. Create a accounts.yaml file which contains the set of pre-existing
+ credentials to use for testing. To make sure you don't have a credentials
+ starvation issue when running in parallel make sure you have at least 2
+ times the number of parallel workers you are using to execute tempest
+ available in the file.
+ #. Provide tempest with the location of you accounts.yaml file with the
+ test_accounts_file option in the auth section
+
+
+Non-locking test accounts
+"""""""""""""""""""""""""
+When tempest was refactored to allow for locking test accounts, the original
+non-tenant isolated case was converted to support the new accounts.yaml file.
+This mechanism is the non-locking test accounts provider. It only makes sense
+to use it if parallel execution isn't needed. If the role restrictions were too
+limiting with the locking accounts provider and tenant isolation is not wanted
+then you can use the non-locking test accounts credential provider without the
+accounts.yaml file. This is also the currently the default configuration for
+tempest, since it doesn't require elevated permissions or the extra file.
+
+To use the non-locking test accounts provider you have 2 ways to configure it.
+First you can specify the sets of credentials in the configuration file like
+detailed above with following 9 options in the identity section:
+
+ #. username
+ #. password
+ #. tenant_name
+ #. admin_username
+ #. admin_password
+ #. admin_tenant_name
+ #. alt_username
+ #. alt_password
+ #. alt_tenant_name
+
+You should use this if you need to specify credentials with different roles.
+(i.e. you want to use admin credentials) However, this isn't a requirement for
+its usage.
+
+You also can use the accounts.yaml file to specify the credentials used for
+testing. This will just allocate them serially so you only need to provide
+a pair of credentials. Do note that all the restrictions associated with
+locking test accounts applies to using the accounts.yaml file this way too.
+The procedure for doing this is very similar to with the locking accounts
+provider just don't set the locking_credentials_provider to true and you
+only should need a single pair of credentials.
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 1f06bc5..cb1c504 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -29,6 +29,15 @@
field_guide/thirdparty
field_guide/unit_tests
+---------------------------
+Tempest Configuration Guide
+---------------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ configuration
+
---------------------
Command Documentation
---------------------
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 0eeb738..d81d3bb 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -125,7 +125,7 @@
# achieved configuring a list of test accounts (boolean value)
# Deprecated group/name - [compute]/allow_tenant_isolation
# Deprecated group/name - [orchestration]/allow_tenant_isolation
-#allow_tenant_isolation = false
+#allow_tenant_isolation = true
# If set to True it enables the Accounts provider, which locks
# credentials to allow for parallel execution with pre-provisioned
@@ -779,6 +779,10 @@
# value)
#dns_servers = 8.8.8.8,8.8.4.4
+# vnic_type to use when Launching instances with pre-configured ports.
+# Supported ports are: ['normal','direct','macvtap'] (string value)
+#port_vnic_type = <None>
+
[network-feature-enabled]
diff --git a/requirements.txt b/requirements.txt
index 94c6fb0..4690329 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,18 +11,17 @@
netaddr>=0.7.12
python-ceilometerclient>=1.0.6
python-glanceclient>=0.15.0
-python-keystoneclient>=1.0.0
-python-novaclient>=2.18.0
-python-neutronclient>=2.3.6,<3
+python-keystoneclient>=1.1.0
+python-neutronclient>=2.3.11,<3
python-cinderclient>=1.1.0
-python-heatclient>=0.2.9
+python-heatclient>=0.3.0
python-ironicclient>=0.2.1
python-saharaclient>=0.7.6
python-swiftclient>=2.2.0
testrepository>=0.0.18
oslo.config>=1.6.0 # Apache-2.0
-six>=1.7.0
+six>=1.9.0
iso8601>=0.1.9
fixtures>=0.3.14
testscenarios>=0.4
-tempest-lib>=0.1.0
+tempest-lib>=0.2.0
diff --git a/tempest/api/baremetal/admin/base.py b/tempest/api/baremetal/admin/base.py
index 3b12b8e..c93dfb8 100644
--- a/tempest/api/baremetal/admin/base.py
+++ b/tempest/api/baremetal/admin/base.py
@@ -11,11 +11,11 @@
# under the License.
import functools
+from tempest_lib import exceptions as lib_exc
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions as exc
from tempest import test
CONF = config.CONF
@@ -53,9 +53,8 @@
"""Base class for Baremetal API tests."""
@classmethod
- def resource_setup(cls):
- super(BaseBaremetalTest, cls).resource_setup()
-
+ def skip_checks(cls):
+ super(BaseBaremetalTest, cls).skip_checks()
if not CONF.service_available.ironic:
skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
raise cls.skipException(skip_msg)
@@ -65,10 +64,22 @@
'testing.' %
(cls.__name__, CONF.baremetal.driver))
raise cls.skipException(skip_msg)
- cls.driver = CONF.baremetal.driver
- mgr = clients.AdminManager()
- cls.client = mgr.baremetal_client
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseBaremetalTest, cls).setup_credentials()
+ cls.mgr = clients.AdminManager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseBaremetalTest, cls).setup_clients()
+ cls.client = cls.mgr.baremetal_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseBaremetalTest, cls).resource_setup()
+
+ cls.driver = CONF.baremetal.driver
cls.power_timeout = CONF.baremetal.power_timeout
cls.created_objects = {}
for resource in RESOURCE_TYPES:
@@ -83,7 +94,7 @@
uuids = cls.created_objects[resource]
delete_method = getattr(cls.client, 'delete_%s' % resource)
for u in uuids:
- delete_method(u, ignore_errors=exc.NotFound)
+ delete_method(u, ignore_errors=lib_exc.NotFound)
finally:
super(BaseBaremetalTest, cls).resource_cleanup()
@@ -104,21 +115,22 @@
@classmethod
@creates('node')
- def create_node(cls, chassis_id, cpu_arch='x86', cpu_num=8, storage=1024,
- memory=4096):
+ def create_node(cls, chassis_id, cpu_arch='x86', cpus=8, local_gb=10,
+ memory_mb=4096):
"""
Wrapper utility for creating test baremetal nodes.
:param cpu_arch: CPU architecture of the node. Default: x86.
- :param cpu_num: Number of CPUs. Default: 8.
- :param storage: Disk size. Default: 1024.
- :param memory: Available RAM. Default: 4096.
+ :param cpus: Number of CPUs. Default: 8.
+ :param local_gb: Disk size. Default: 10.
+ :param memory_mb: Available RAM. Default: 4096.
:return: Created node.
"""
resp, body = cls.client.create_node(chassis_id, cpu_arch=cpu_arch,
- cpu_num=cpu_num, storage=storage,
- memory=memory, driver=cls.driver)
+ cpus=cpus, local_gb=local_gb,
+ memory_mb=memory_mb,
+ driver=cls.driver)
return resp, body
diff --git a/tempest/api/baremetal/admin/test_api_discovery.py b/tempest/api/baremetal/admin/test_api_discovery.py
index 09788f2..f0b8b7f 100644
--- a/tempest/api/baremetal/admin/test_api_discovery.py
+++ b/tempest/api/baremetal/admin/test_api_discovery.py
@@ -18,6 +18,7 @@
"""Tests for API discovery features."""
@test.attr(type='smoke')
+ @test.idempotent_id('a3c27e94-f56c-42c4-8600-d6790650b9c5')
def test_api_versions(self):
_, descr = self.client.get_api_description()
expected_versions = ('v1',)
@@ -27,12 +28,14 @@
self.assertIn(v, versions)
@test.attr(type='smoke')
+ @test.idempotent_id('896283a6-488e-4f31-af78-6614286cbe0d')
def test_default_version(self):
_, descr = self.client.get_api_description()
default_version = descr['default_version']
self.assertEqual(default_version['id'], 'v1')
@test.attr(type='smoke')
+ @test.idempotent_id('abc0b34d-e684-4546-9728-ab7a9ad9f174')
def test_version_1_resources(self):
_, descr = self.client.get_version_description(version='v1')
expected_resources = ('nodes', 'chassis',
diff --git a/tempest/api/baremetal/admin/test_chassis.py b/tempest/api/baremetal/admin/test_chassis.py
index 6f83412..da32f71 100644
--- a/tempest/api/baremetal/admin/test_chassis.py
+++ b/tempest/api/baremetal/admin/test_chassis.py
@@ -11,9 +11,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.baremetal.admin import base
from tempest.common.utils import data_utils
-from tempest import exceptions as exc
from tempest import test
@@ -33,12 +34,14 @@
self.assertEqual(value, actual[key])
@test.attr(type='smoke')
+ @test.idempotent_id('7c5a2e09-699c-44be-89ed-2bc189992d42')
def test_create_chassis(self):
descr = data_utils.rand_name('test-chassis-')
_, chassis = self.create_chassis(description=descr)
self.assertEqual(chassis['description'], descr)
@test.attr(type='smoke')
+ @test.idempotent_id('cabe9c6f-dc16-41a7-b6b9-0a90c212edd5')
def test_create_chassis_unicode_description(self):
# Use a unicode string for testing:
# 'We ♡ OpenStack in Ukraine'
@@ -47,25 +50,29 @@
self.assertEqual(chassis['description'], descr)
@test.attr(type='smoke')
+ @test.idempotent_id('c84644df-31c4-49db-a307-8942881f41c0')
def test_show_chassis(self):
_, chassis = self.client.show_chassis(self.chassis['uuid'])
self._assertExpected(self.chassis, chassis)
@test.attr(type="smoke")
+ @test.idempotent_id('29c9cd3f-19b5-417b-9864-99512c3b33b3')
def test_list_chassis(self):
_, body = self.client.list_chassis()
self.assertIn(self.chassis['uuid'],
[i['uuid'] for i in body['chassis']])
@test.attr(type='smoke')
+ @test.idempotent_id('5ae649ad-22d1-4fe1-bbc6-97227d199fb3')
def test_delete_chassis(self):
_, body = self.create_chassis()
uuid = body['uuid']
self.delete_chassis(uuid)
- self.assertRaises(exc.NotFound, self.client.show_chassis, uuid)
+ self.assertRaises(lib_exc.NotFound, self.client.show_chassis, uuid)
@test.attr(type='smoke')
+ @test.idempotent_id('cda8a41f-6be2-4cbf-840c-994b00a89b44')
def test_update_chassis(self):
_, body = self.create_chassis()
uuid = body['uuid']
@@ -77,6 +84,7 @@
self.assertEqual(chassis['description'], new_description)
@test.attr(type='smoke')
+ @test.idempotent_id('76305e22-a4e2-4ab3-855c-f4e2368b9335')
def test_chassis_node_list(self):
_, node = self.create_node(self.chassis['uuid'])
_, body = self.client.list_chassis_nodes(self.chassis['uuid'])
diff --git a/tempest/api/baremetal/admin/test_drivers.py b/tempest/api/baremetal/admin/test_drivers.py
index 9d99295..de04562 100644
--- a/tempest/api/baremetal/admin/test_drivers.py
+++ b/tempest/api/baremetal/admin/test_drivers.py
@@ -27,12 +27,14 @@
cls.driver_name = CONF.baremetal.driver
@test.attr(type="smoke")
+ @test.idempotent_id('5aed2790-7592-4655-9b16-99abcc2e6ec5')
def test_list_drivers(self):
_, drivers = self.client.list_drivers()
self.assertIn(self.driver_name,
[d['name'] for d in drivers['drivers']])
@test.attr(type="smoke")
+ @test.idempotent_id('fb3287a3-c4d7-44bf-ae9d-1eef906d78ce')
def test_show_driver(self):
_, driver = self.client.show_driver(self.driver_name)
self.assertEqual(self.driver_name, driver['name'])
diff --git a/tempest/api/baremetal/admin/test_nodes.py b/tempest/api/baremetal/admin/test_nodes.py
index 41c12c6..f031614 100644
--- a/tempest/api/baremetal/admin/test_nodes.py
+++ b/tempest/api/baremetal/admin/test_nodes.py
@@ -11,11 +11,11 @@
# under the License.
import six
+from tempest_lib import exceptions as lib_exc
from tempest.api.baremetal.admin import base
from tempest.common.utils import data_utils
from tempest.common import waiters
-from tempest import exceptions as exc
from tempest import test
@@ -47,35 +47,41 @@
return instance_uuid
@test.attr(type='smoke')
+ @test.idempotent_id('4e939eb2-8a69-4e84-8652-6fffcbc9db8f')
def test_create_node(self):
params = {'cpu_arch': 'x86_64',
- 'cpu_num': '12',
- 'storage': '10240',
- 'memory': '1024'}
+ 'cpus': '12',
+ 'local_gb': '10',
+ 'memory_mb': '1024'}
_, body = self.create_node(self.chassis['uuid'], **params)
self._assertExpected(params, body['properties'])
@test.attr(type='smoke')
+ @test.idempotent_id('9ade60a4-505e-4259-9ec4-71352cbbaf47')
def test_delete_node(self):
_, node = self.create_node(self.chassis['uuid'])
self.delete_node(node['uuid'])
- self.assertRaises(exc.NotFound, self.client.show_node, node['uuid'])
+ self.assertRaises(lib_exc.NotFound, self.client.show_node,
+ node['uuid'])
@test.attr(type='smoke')
+ @test.idempotent_id('55451300-057c-4ecf-8255-ba42a83d3a03')
def test_show_node(self):
_, loaded_node = self.client.show_node(self.node['uuid'])
self._assertExpected(self.node, loaded_node)
@test.attr(type='smoke')
+ @test.idempotent_id('4ca123c4-160d-4d8d-a3f7-15feda812263')
def test_list_nodes(self):
_, body = self.client.list_nodes()
self.assertIn(self.node['uuid'],
[i['uuid'] for i in body['nodes']])
@test.attr(type='smoke')
+ @test.idempotent_id('85b1f6e0-57fd-424c-aeff-c3422920556f')
def test_list_nodes_association(self):
_, body = self.client.list_nodes(associated=True)
self.assertNotIn(self.node['uuid'],
@@ -90,6 +96,7 @@
self.assertNotIn(self.node['uuid'], [n['uuid'] for n in body['nodes']])
@test.attr(type='smoke')
+ @test.idempotent_id('18c4ebd8-f83a-4df7-9653-9fb33a329730')
def test_node_port_list(self):
_, port = self.create_port(self.node['uuid'],
data_utils.rand_mac_address())
@@ -98,30 +105,33 @@
[p['uuid'] for p in body['ports']])
@test.attr(type='smoke')
+ @test.idempotent_id('72591acb-f215-49db-8395-710d14eb86ab')
def test_node_port_list_no_ports(self):
_, node = self.create_node(self.chassis['uuid'])
_, body = self.client.list_node_ports(node['uuid'])
self.assertEmpty(body['ports'])
@test.attr(type='smoke')
+ @test.idempotent_id('4fed270a-677a-4d19-be87-fd38ae490320')
def test_update_node(self):
props = {'cpu_arch': 'x86_64',
- 'cpu_num': '12',
- 'storage': '10',
- 'memory': '128'}
+ 'cpus': '12',
+ 'local_gb': '10',
+ 'memory_mb': '128'}
_, node = self.create_node(self.chassis['uuid'], **props)
new_p = {'cpu_arch': 'x86',
- 'cpu_num': '1',
- 'storage': '10000',
- 'memory': '12300'}
+ 'cpus': '1',
+ 'local_gb': '10000',
+ 'memory_mb': '12300'}
_, body = self.client.update_node(node['uuid'], properties=new_p)
_, node = self.client.show_node(node['uuid'])
self._assertExpected(new_p, node['properties'])
@test.attr(type='smoke')
+ @test.idempotent_id('cbf1f515-5f4b-4e49-945c-86bcaccfeb1d')
def test_validate_driver_interface(self):
_, body = self.client.validate_driver_interface(self.node['uuid'])
core_interfaces = ['power', 'deploy']
@@ -129,10 +139,12 @@
self.assertIn(interface, body)
@test.attr(type='smoke')
+ @test.idempotent_id('5519371c-26a2-46e9-aa1a-f74226e9d71f')
def test_set_node_boot_device(self):
self.client.set_node_boot_device(self.node['uuid'], 'pxe')
@test.attr(type='smoke')
+ @test.idempotent_id('9ea73775-f578-40b9-bc34-efc639c4f21f')
def test_get_node_boot_device(self):
body = self.client.get_node_boot_device(self.node['uuid'])
self.assertIn('boot_device', body)
@@ -141,12 +153,14 @@
self.assertTrue(isinstance(body['persistent'], bool))
@test.attr(type='smoke')
+ @test.idempotent_id('3622bc6f-3589-4bc2-89f3-50419c66b133')
def test_get_node_supported_boot_devices(self):
body = self.client.get_node_supported_boot_devices(self.node['uuid'])
self.assertIn('supported_boot_devices', body)
self.assertTrue(isinstance(body['supported_boot_devices'], list))
@test.attr(type='smoke')
+ @test.idempotent_id('f63b6288-1137-4426-8cfe-0d5b7eb87c06')
def test_get_console(self):
_, body = self.client.get_console(self.node['uuid'])
con_info = ['console_enabled', 'console_info']
@@ -154,6 +168,7 @@
self.assertIn(key, body)
@test.attr(type='smoke')
+ @test.idempotent_id('80504575-9b21-4670-92d1-143b948f9437')
def test_set_console_mode(self):
self.client.set_console_mode(self.node['uuid'], True)
@@ -161,6 +176,7 @@
self.assertEqual(True, body['console_enabled'])
@test.attr(type='smoke')
+ @test.idempotent_id('b02a4f38-5e8b-44b2-aed2-a69a36ecfd69')
def test_get_node_by_instance_uuid(self):
instance_uuid = self._associate_node_with_instance()
_, body = self.client.show_node_by_instance_uuid(instance_uuid)
diff --git a/tempest/api/baremetal/admin/test_nodestates.py b/tempest/api/baremetal/admin/test_nodestates.py
index f4f8054..bcb8b78 100644
--- a/tempest/api/baremetal/admin/test_nodestates.py
+++ b/tempest/api/baremetal/admin/test_nodestates.py
@@ -42,12 +42,14 @@
raise exceptions.TimeoutException(message)
@test.attr(type='smoke')
+ @test.idempotent_id('cd8afa5e-3f57-4e43-8185-beb83d3c9015')
def test_list_nodestates(self):
_, nodestates = self.client.list_nodestates(self.node['uuid'])
for key in nodestates:
self.assertEqual(nodestates[key], self.node[key])
@test.attr(type='smoke')
+ @test.idempotent_id('fc5b9320-0c98-4e5a-8848-877fe5a0322c')
def test_set_node_power_state(self):
_, node = self.create_node(self.chassis['uuid'])
states = ["power on", "rebooting", "power off"]
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
index 89447e0..bbd2801 100644
--- a/tempest/api/baremetal/admin/test_ports.py
+++ b/tempest/api/baremetal/admin/test_ports.py
@@ -11,10 +11,10 @@
# under the License.
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
from tempest.api.baremetal.admin import base
from tempest.common.utils import data_utils
-from tempest import exceptions as exc
from tempest import test
@@ -37,6 +37,7 @@
self.assertEqual(value, actual[key])
@test.attr(type='smoke')
+ @test.idempotent_id('83975898-2e50-42ed-b5f0-e510e36a0b56')
def test_create_port(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -48,6 +49,7 @@
self._assertExpected(port, body)
@test.attr(type='smoke')
+ @test.idempotent_id('d1f6b249-4cf6-4fe6-9ed6-a6e84b1bf67b')
def test_create_port_specifying_uuid(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -61,6 +63,7 @@
@decorators.skip_because(bug='1398350')
@test.attr(type='smoke')
+ @test.idempotent_id('4a02c4b0-6573-42a4-a513-2e36ad485b62')
def test_create_port_with_extra(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -74,6 +77,7 @@
self._assertExpected(port, body)
@test.attr(type='smoke')
+ @test.idempotent_id('1bf257a9-aea3-494e-89c0-63f657ab4fdd')
def test_delete_port(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -81,19 +85,23 @@
self.delete_port(port['uuid'])
- self.assertRaises(exc.NotFound, self.client.show_port, port['uuid'])
+ self.assertRaises(lib_exc.NotFound, self.client.show_port,
+ port['uuid'])
@test.attr(type='smoke')
+ @test.idempotent_id('9fa77ab5-ce59-4f05-baac-148904ba1597')
def test_show_port(self):
_, port = self.client.show_port(self.port['uuid'])
self._assertExpected(self.port, port)
@test.attr(type='smoke')
+ @test.idempotent_id('7c1114ff-fc3f-47bb-bc2f-68f61620ba8b')
def test_show_port_by_address(self):
_, port = self.client.show_port_by_address(self.port['address'])
self._assertExpected(self.port, port['ports'][0])
@test.attr(type='smoke')
+ @test.idempotent_id('bd773405-aea5-465d-b576-0ab1780069e5')
def test_show_port_with_links(self):
_, port = self.client.show_port(self.port['uuid'])
self.assertIn('links', port.keys())
@@ -101,6 +109,7 @@
self.assertIn(port['uuid'], port['links'][0]['href'])
@test.attr(type='smoke')
+ @test.idempotent_id('b5e91854-5cd7-4a8e-bb35-3e0a1314606d')
def test_list_ports(self):
_, body = self.client.list_ports()
self.assertIn(self.port['uuid'],
@@ -111,12 +120,14 @@
port['links'][0]['href'])
@test.attr(type='smoke')
+ @test.idempotent_id('324a910e-2f80-4258-9087-062b5ae06240')
def test_list_with_limit(self):
_, body = self.client.list_ports(limit=3)
next_marker = body['ports'][-1]['uuid']
self.assertIn(next_marker, body['next'])
+ @test.idempotent_id('8a94b50f-9895-4a63-a574-7ecff86e5875')
def test_list_ports_details(self):
node_id = self.node['uuid']
@@ -141,6 +152,7 @@
self.validate_self_link('ports', port['uuid'],
port['links'][0]['href'])
+ @test.idempotent_id('8a03f688-7d75-4ecd-8cbc-e06b8f346738')
def test_list_ports_details_with_address(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -154,6 +166,7 @@
self.assertEqual(address, body['ports'][0]['address'])
@test.attr(type='smoke')
+ @test.idempotent_id('9c26298b-1bcb-47b7-9b9e-8bdd6e3c4aba')
def test_update_port_replace(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -186,6 +199,7 @@
self.assertEqual(new_extra, body['extra'])
@test.attr(type='smoke')
+ @test.idempotent_id('d7e7fece-6ed9-460a-9ebe-9267217e8580')
def test_update_port_remove(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -213,6 +227,7 @@
self.assertEqual(address, body['address'])
@test.attr(type='smoke')
+ @test.idempotent_id('241288b3-e98a-400f-a4d7-d1f716146361')
def test_update_port_add(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -235,6 +250,7 @@
@decorators.skip_because(bug='1398350')
@test.attr(type='smoke')
+ @test.idempotent_id('5309e897-0799-4649-a982-0179b04c3876')
def test_update_port_mixed_ops(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
diff --git a/tempest/api/baremetal/admin/test_ports_negative.py b/tempest/api/baremetal/admin/test_ports_negative.py
index 8080eb6..2e79883 100644
--- a/tempest/api/baremetal/admin/test_ports_negative.py
+++ b/tempest/api/baremetal/admin/test_ports_negative.py
@@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.baremetal.admin import base
from tempest.common.utils import data_utils
-from tempest import exceptions as exc
from tempest import test
@@ -26,84 +27,96 @@
_, self.node = self.create_node(self.chassis['uuid'])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('0a6ee1f7-d0d9-4069-8778-37f3aa07303a')
def test_create_port_malformed_mac(self):
node_id = self.node['uuid']
address = 'malformed:mac'
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_port, node_id=node_id, address=address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('30277ee8-0c60-4f1d-b125-0e51c2f43369')
def test_create_port_nonexsistent_node_id(self):
node_id = str(data_utils.rand_uuid())
address = data_utils.rand_mac_address()
- self.assertRaises(exc.BadRequest, self.create_port, node_id=node_id,
- address=address)
+ self.assertRaises(lib_exc.BadRequest, self.create_port,
+ node_id=node_id, address=address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('029190f6-43e1-40a3-b64a-65173ba653a3')
def test_show_port_malformed_uuid(self):
- self.assertRaises(exc.BadRequest, self.client.show_port,
+ self.assertRaises(lib_exc.BadRequest, self.client.show_port,
'malformed:uuid')
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('0d00e13d-e2e0-45b1-bcbc-55a6d90ca793')
def test_show_port_nonexistent_uuid(self):
- self.assertRaises(exc.NotFound, self.client.show_port,
+ self.assertRaises(lib_exc.NotFound, self.client.show_port,
data_utils.rand_uuid())
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('4ad85266-31e9-4942-99ac-751897dc9e23')
def test_show_port_by_mac_not_allowed(self):
- self.assertRaises(exc.BadRequest, self.client.show_port,
+ self.assertRaises(lib_exc.BadRequest, self.client.show_port,
data_utils.rand_mac_address())
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('89a34380-3c61-4c32-955c-2cd9ce94da21')
def test_create_port_duplicated_port_uuid(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
uuid = data_utils.rand_uuid()
self.create_port(node_id=node_id, address=address, uuid=uuid)
- self.assertRaises(exc.Conflict, self.create_port, node_id=node_id,
+ self.assertRaises(lib_exc.Conflict, self.create_port, node_id=node_id,
address=address, uuid=uuid)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('65e84917-733c-40ae-ae4b-96a4adff931c')
def test_create_port_no_mandatory_field_node_id(self):
address = data_utils.rand_mac_address()
- self.assertRaises(exc.BadRequest, self.create_port, node_id=None,
+ self.assertRaises(lib_exc.BadRequest, self.create_port, node_id=None,
address=address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('bcea3476-7033-4183-acfe-e56a30809b46')
def test_create_port_no_mandatory_field_mac(self):
node_id = self.node['uuid']
- self.assertRaises(exc.BadRequest, self.create_port, node_id=node_id,
- address=None)
+ self.assertRaises(lib_exc.BadRequest, self.create_port,
+ node_id=node_id, address=None)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('2b51cd18-fb95-458b-9780-e6257787b649')
def test_create_port_malformed_port_uuid(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
uuid = 'malformed:uuid'
- self.assertRaises(exc.BadRequest, self.create_port, node_id=node_id,
- address=address, uuid=uuid)
+ self.assertRaises(lib_exc.BadRequest, self.create_port,
+ node_id=node_id, address=address, uuid=uuid)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('583a6856-6a30-4ac4-889f-14e2adff8105')
def test_create_port_malformed_node_id(self):
address = data_utils.rand_mac_address()
- self.assertRaises(exc.BadRequest, self.create_port,
+ self.assertRaises(lib_exc.BadRequest, self.create_port,
node_id='malformed:nodeid', address=address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('e27f8b2e-42c6-4a43-a3cd-accff716bc5c')
def test_create_port_duplicated_mac(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
self.create_port(node_id=node_id, address=address)
- self.assertRaises(exc.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.create_port, node_id=node_id,
address=address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('8907082d-ac5e-4be3-b05f-d072ede82020')
def test_update_port_by_mac_not_allowed(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -115,11 +128,12 @@
'op': 'replace',
'value': 'new-value'}]
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_port, address,
patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('df1ac70c-db9f-41d9-90f1-78cd6b905718')
def test_update_port_nonexistent(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -134,10 +148,11 @@
patch = [{'path': '/extra/key',
'op': 'replace',
'value': 'new-value'}]
- self.assertRaises(exc.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('c701e315-aa52-41ea-817c-65c5ca8ca2a8')
def test_update_port_malformed_port_uuid(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -145,12 +160,13 @@
self.create_port(node_id=node_id, address=address)
new_address = data_utils.rand_mac_address()
- self.assertRaises(exc.BadRequest, self.client.update_port,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port,
uuid='malformed:uuid',
patch=[{'path': '/address', 'op': 'replace',
'value': new_address}])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('f8f15803-34d6-45dc-b06f-e5e04bf1b38b')
def test_update_port_add_nonexistent_property(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -158,11 +174,12 @@
_, port = self.create_port(node_id=node_id, address=address)
port_id = port['uuid']
- self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
[{'path': '/nonexistent', ' op': 'add',
'value': 'value'}])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('898ec904-38b1-4fcb-9584-1187d4263a2a')
def test_update_port_replace_node_id_with_malformed(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -173,10 +190,11 @@
patch = [{'path': '/node_uuid',
'op': 'replace',
'value': 'malformed:node_uuid'}]
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('2949f30f-5f59-43fa-a6d9-4eac578afab4')
def test_update_port_replace_mac_with_duplicated(self):
node_id = self.node['uuid']
address1 = data_utils.rand_mac_address()
@@ -190,10 +208,11 @@
patch = [{'path': '/address',
'op': 'replace',
'value': address1}]
- self.assertRaises(exc.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('97f6e048-6e4f-4eba-a09d-fbbc78b77a77')
def test_update_port_replace_node_id_with_nonexistent(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -204,10 +223,11 @@
patch = [{'path': '/node_uuid',
'op': 'replace',
'value': data_utils.rand_uuid()}]
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('375022c5-9e9e-4b11-9ca4-656729c0c9b2')
def test_update_port_replace_mac_with_malformed(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -219,10 +239,11 @@
'op': 'replace',
'value': 'malformed:mac'}]
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('5722b853-03fc-4854-8308-2036a1b67d85')
def test_update_port_replace_nonexistent_property(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -232,10 +253,11 @@
patch = [{'path': '/nonexistent', ' op': 'replace', 'value': 'value'}]
- self.assertRaises(exc.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_port, port_id, patch)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('ae2696ca-930a-4a7f-918f-30ae97c60f56')
def test_update_port_remove_mandatory_field_mac(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -243,10 +265,11 @@
_, port = self.create_port(node_id=node_id, address=address)
port_id = port['uuid']
- self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
[{'path': '/address', 'op': 'remove'}])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('5392c1f0-2071-4697-9064-ec2d63019018')
def test_update_port_remove_mandatory_field_port_uuid(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -254,10 +277,11 @@
_, port = self.create_port(node_id=node_id, address=address)
port_id = port['uuid']
- self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
[{'path': '/uuid', 'op': 'remove'}])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('06b50d82-802a-47ef-b079-0a3311cf85a2')
def test_update_port_remove_nonexistent_property(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -265,18 +289,20 @@
_, port = self.create_port(node_id=node_id, address=address)
port_id = port['uuid']
- self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
[{'path': '/nonexistent', 'op': 'remove'}])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('03d42391-2145-4a6c-95bf-63fe55eb64fd')
def test_delete_port_by_mac_not_allowed(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
self.create_port(node_id=node_id, address=address)
- self.assertRaises(exc.BadRequest, self.client.delete_port, address)
+ self.assertRaises(lib_exc.BadRequest, self.client.delete_port, address)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('0629e002-818e-4763-b25b-ae5e07b1cb23')
def test_update_port_mixed_ops_integrity(self):
node_id = self.node['uuid']
address = data_utils.rand_mac_address()
@@ -304,7 +330,7 @@
'op': 'replace',
'value': 'value'}]
- self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_port, port_id,
patch)
# patch should not be applied
diff --git a/tempest/api/compute/admin/test_agents.py b/tempest/api/compute/admin/test_agents.py
index 425ce13..2bd15ac 100644
--- a/tempest/api/compute/admin/test_agents.py
+++ b/tempest/api/compute/admin/test_agents.py
@@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest.openstack.common import log
from tempest import test
@@ -43,7 +44,7 @@
def tearDown(self):
try:
self.client.delete_agent(self.agent_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
except Exception:
LOG.exception('Exception raised deleting agent %s', self.agent_id)
@@ -60,6 +61,7 @@
return kwargs
@test.attr(type='gate')
+ @test.idempotent_id('1fc6bdc8-0b6d-4cc7-9f30-9b04fabe5b90')
def test_create_agent(self):
# Create an agent.
params = self._param_helper(
@@ -72,6 +74,7 @@
self.assertEqual(value, body[expected_item])
@test.attr(type='gate')
+ @test.idempotent_id('dc9ffd51-1c50-4f0e-a820-ae6d2a568a9e')
def test_update_agent(self):
# Update an agent.
params = self._param_helper(
@@ -82,6 +85,7 @@
self.assertEqual(value, body[expected_item])
@test.attr(type='gate')
+ @test.idempotent_id('470e0b89-386f-407b-91fd-819737d0b335')
def test_delete_agent(self):
# Delete an agent.
self.client.delete_agent(self.agent_id)
@@ -91,6 +95,7 @@
self.assertNotIn(self.agent_id, map(lambda x: x['agent_id'], agents))
@test.attr(type='gate')
+ @test.idempotent_id('6a326c69-654b-438a-80a3-34bcc454e138')
def test_list_agents(self):
# List all agents.
agents = self.client.list_agents()
@@ -98,6 +103,7 @@
self.assertIn(self.agent_id, map(lambda x: x['agent_id'], agents))
@test.attr(type='gate')
+ @test.idempotent_id('eabadde4-3cd7-4ec4-a4b5-5a936d2d4408')
def test_list_agents_with_filter(self):
# List the agent builds by the filter.
params = self._param_helper(
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index a866ede..e3b0151 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -13,10 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -45,10 +46,11 @@
try:
self.client.delete_aggregate(aggregate_id)
# if aggregate not found, it depict it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@test.attr(type='gate')
+ @test.idempotent_id('0d148aa3-d54c-4317-aa8d-42040a475e20')
def test_aggregate_create_delete(self):
# Create and delete an aggregate.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -61,6 +63,7 @@
self.client.wait_for_resource_deletion(aggregate['id'])
@test.attr(type='gate')
+ @test.idempotent_id('5873a6f8-671a-43ff-8838-7ce430bb6d0b')
def test_aggregate_create_delete_with_az(self):
# Create and delete an aggregate.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -75,6 +78,7 @@
self.client.wait_for_resource_deletion(aggregate['id'])
@test.attr(type='gate')
+ @test.idempotent_id('68089c38-04b1-4758-bdf0-cf0daec4defd')
def test_aggregate_create_verify_entry_in_list(self):
# Create an aggregate and ensure it is listed.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -87,6 +91,7 @@
aggregates))
@test.attr(type='gate')
+ @test.idempotent_id('36ec92ca-7a73-43bc-b920-7531809e8540')
def test_aggregate_create_update_metadata_get_details(self):
# Create an aggregate and ensure its details are returned.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -109,6 +114,7 @@
self.assertEqual(meta, body["metadata"])
@test.attr(type='gate')
+ @test.idempotent_id('4d2b2004-40fa-40a1-aab2-66f4dab81beb')
def test_aggregate_create_update_with_az(self):
# Update an aggregate and ensure properties are updated correctly
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -138,6 +144,7 @@
aggregates))
@test.attr(type='gate')
+ @test.idempotent_id('c8e85064-e79b-4906-9931-c11c24294d02')
def test_aggregate_add_remove_host(self):
# Add an host to the given aggregate and remove.
self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -158,6 +165,7 @@
self.assertNotIn(self.host, body['hosts'])
@test.attr(type='gate')
+ @test.idempotent_id('7f6a1cc5-2446-4cdb-9baa-b6ae0a919b72')
def test_aggregate_add_host_list(self):
# Add an host to the given aggregate and list.
self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -176,6 +184,7 @@
self.assertIn(self.host, agg['hosts'])
@test.attr(type='gate')
+ @test.idempotent_id('eeef473c-7c52-494d-9f09-2ed7fc8fc036')
def test_aggregate_add_host_get_details(self):
# Add an host to the given aggregate and get details.
self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -191,6 +200,7 @@
self.assertIn(self.host, body['hosts'])
@test.attr(type='gate')
+ @test.idempotent_id('96be03c7-570d-409c-90f8-e4db3c646996')
def test_aggregate_add_host_create_server_with_az(self):
# Add an host to the given aggregate and create a server.
self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -203,8 +213,8 @@
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
server_name = data_utils.rand_name('test_server_')
admin_servers_client = self.os_adm.servers_client
- resp, server = self.create_test_server(name=server_name,
- availability_zone=az_name,
- wait_until='ACTIVE')
- resp, body = admin_servers_client.get_server(server['id'])
+ server = self.create_test_server(name=server_name,
+ availability_zone=az_name,
+ wait_until='ACTIVE')
+ body = admin_servers_client.get_server(server['id'])
self.assertEqual(self.host, body[self._host_key])
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index a450e5d..02e2b0b 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -13,10 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -40,80 +41,90 @@
cls.host = hosts[0]
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
def test_aggregate_create_as_user(self):
# Regular user is not allowed to create an aggregate.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.create_aggregate,
name=aggregate_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3b8a1929-3793-4e92-bcb4-dfa572ee6c1d')
def test_aggregate_create_aggregate_name_length_less_than_1(self):
# the length of aggregate name should >= 1 and <=255
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_aggregate,
name='')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4c194563-543b-4e70-a719-557bbe947fac')
def test_aggregate_create_aggregate_name_length_exceeds_255(self):
# the length of aggregate name should >= 1 and <=255
aggregate_name = 'a' * 256
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_aggregate,
name=aggregate_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9c23a291-b0b1-487b-b464-132e061151b3')
def test_aggregate_create_with_existent_aggregate_name(self):
# creating an aggregate with existent aggregate name is forbidden
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.create_aggregate,
name=aggregate_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
def test_aggregate_delete_as_user(self):
# Regular user is not allowed to delete an aggregate.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.delete_aggregate,
aggregate['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b7d475a6-5dcd-4ff4-b70a-cd9de66a6672')
def test_aggregate_list_as_user(self):
# Regular user is not allowed to list aggregates.
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.list_aggregates)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('557cad12-34c9-4ff4-95f0-22f0dfbaf7dc')
def test_aggregate_get_details_as_user(self):
# Regular user is not allowed to get aggregate details.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.get_aggregate,
aggregate['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c74f4bf1-4708-4ff2-95a0-f49eaca951bd')
def test_aggregate_delete_with_invalid_id(self):
# Delete an aggregate with invalid id should raise exceptions.
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_aggregate, -1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3c916244-2c46-49a4-9b55-b20bb0ae512c')
def test_aggregate_get_details_with_invalid_id(self):
# Get aggregate details with invalid id should raise exceptions.
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_aggregate, -1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
def test_aggregate_add_non_exist_host(self):
# Adding a non-exist host to an aggregate should raise exceptions.
hosts_all = self.os_adm.hosts_client.list_hosts()
@@ -127,21 +138,23 @@
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.NotFound, self.client.add_host,
+ self.assertRaises(lib_exc.NotFound, self.client.add_host,
aggregate['id'], non_exist_host)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7324c334-bd13-4c93-8521-5877322c3d51')
def test_aggregate_add_host_as_user(self):
# Regular user is not allowed to add a host to an aggregate.
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.add_host,
aggregate['id'], self.host)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
def test_aggregate_add_existent_host(self):
self.useFixture(fixtures.LockFixture('availability_zone'))
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
@@ -151,10 +164,11 @@
self.client.add_host(aggregate['id'], self.host)
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
- self.assertRaises(exceptions.Conflict, self.client.add_host,
+ self.assertRaises(lib_exc.Conflict, self.client.add_host,
aggregate['id'], self.host)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7a53af20-137a-4e44-a4ae-e19260e626d9')
def test_aggregate_remove_host_as_user(self):
# Regular user is not allowed to remove a host from an aggregate.
self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -164,16 +178,17 @@
self.client.add_host(aggregate['id'], self.host)
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.remove_host,
aggregate['id'], self.host)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
def test_aggregate_remove_nonexistent_host(self):
non_exist_host = data_utils.rand_name('nonexist_host_')
aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
aggregate = self.client.create_aggregate(name=aggregate_name)
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
- self.assertRaises(exceptions.NotFound, self.client.remove_host,
+ self.assertRaises(lib_exc.NotFound, self.client.remove_host,
aggregate['id'], non_exist_host)
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index e88fecb..9d24b00 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -29,16 +29,15 @@
cls.client = cls.availability_zone_admin_client
@test.attr(type='gate')
+ @test.idempotent_id('d3431479-8a09-4f76-aa2d-26dc580cb27c')
def test_get_availability_zone_list(self):
# List of availability zone
- resp, availability_zone = self.client.get_availability_zone_list()
- self.assertEqual(200, resp.status)
+ availability_zone = self.client.get_availability_zone_list()
self.assertTrue(len(availability_zone) > 0)
@test.attr(type='gate')
+ @test.idempotent_id('ef726c58-530f-44c2-968c-c7bed22d5b8c')
def test_get_availability_zone_list_detail(self):
# List of availability zones and available services
- resp, availability_zone = \
- self.client.get_availability_zone_list_detail()
- self.assertEqual(200, resp.status)
+ availability_zone = self.client.get_availability_zone_list_detail()
self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/admin/test_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index d062b0c..caecddc 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -29,9 +30,10 @@
cls.non_adm_client = cls.availability_zone_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bf34dca2-fdc3-4073-9c02-7648d9eae0d7')
def test_get_availability_zone_list_detail_with_non_admin_user(self):
# List of availability zones and available services with
# non-administrator user
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_availability_zone_list_detail)
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
new file mode 100644
index 0000000..1381f80
--- /dev/null
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -0,0 +1,44 @@
+# 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.api.compute import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class BaremetalNodesAdminTestJSON(base.BaseV2ComputeAdminTest):
+ """
+ Tests Baremetal API
+ """
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaremetalNodesAdminTestJSON, cls).resource_setup()
+ if not CONF.service_available.ironic:
+ skip_msg = ('%s skipped as Ironic is not available' % cls.__name__)
+ raise cls.skipException(skip_msg)
+ cls.client = cls.os_adm.baremetal_nodes_client
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('e475aa6e-416d-4fa4-b3af-28d5e84250fb')
+ def test_list_baremetal_nodes(self):
+ # List all baremetal nodes.
+ baremetal_nodes = self.client.list_baremetal_nodes()
+ self.assertNotEmpty(baremetal_nodes, "No baremetal nodes found.")
+
+ for node in baremetal_nodes:
+ baremetal_node = self.client.get_baremetal_node(node['id'])
+ self.assertEqual(node['id'], baremetal_node['id'])
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index d1d13a0..820b9b0 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -29,8 +29,8 @@
msg = ("%s skipped as neutron is available" % cls.__name__)
raise cls.skipException(msg)
cls.client = cls.os_adm.fixed_ips_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
- resp, server = cls.servers_client.get_server(server['id'])
+ server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.servers_client.get_server(server['id'])
for ip_set in server['addresses']:
for ip in server['addresses'][ip_set]:
if ip['OS-EXT-IPS:type'] == 'fixed':
@@ -40,21 +40,22 @@
break
@test.attr(type='gate')
+ @test.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
@test.services('network')
def test_list_fixed_ip_details(self):
- resp, fixed_ip = self.client.get_fixed_ip_details(self.ip)
+ fixed_ip = self.client.get_fixed_ip_details(self.ip)
self.assertEqual(fixed_ip['address'], self.ip)
@test.attr(type='gate')
+ @test.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
@test.services('network')
def test_set_reserve(self):
body = {"reserve": "None"}
- resp, body = self.client.reserve_fixed_ip(self.ip, body)
- self.assertEqual(resp.status, 202)
+ self.client.reserve_fixed_ip(self.ip, body)
@test.attr(type='gate')
+ @test.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
@test.services('network')
def test_set_unreserve(self):
body = {"unreserve": "None"}
- resp, body = self.client.reserve_fixed_ip(self.ip, body)
- self.assertEqual(resp.status, 202)
+ self.client.reserve_fixed_ip(self.ip, body)
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index e7022db..df3c390 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -30,8 +31,8 @@
raise cls.skipException(msg)
cls.client = cls.os_adm.fixed_ips_client
cls.non_admin_client = cls.fixed_ips_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
- resp, server = cls.servers_client.get_server(server['id'])
+ server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.servers_client.get_server(server['id'])
for ip_set in server['addresses']:
for ip in server['addresses'][ip_set]:
if ip['OS-EXT-IPS:type'] == 'fixed':
@@ -41,28 +42,32 @@
break
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
@test.services('network')
def test_list_fixed_ip_details_with_non_admin_user(self):
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.get_fixed_ip_details, self.ip)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
@test.services('network')
def test_set_reserve_with_non_admin_user(self):
body = {"reserve": "None"}
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.reserve_fixed_ip,
self.ip, body)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
@test.services('network')
def test_set_unreserve_with_non_admin_user(self):
body = {"unreserve": "None"}
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.reserve_fixed_ip,
self.ip, body)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
@test.services('network')
def test_set_reserve_with_invalid_ip(self):
# NOTE(maurosr): since this exercises the same code snippet, we do it
@@ -71,14 +76,15 @@
# 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((exceptions.NotFound, exceptions.BadRequest),
+ self.assertRaises((lib_exc.NotFound, lib_exc.BadRequest),
self.client.reserve_fixed_ip,
"my.invalid.ip", body)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
@test.services('network')
def test_fixed_ip_with_invalid_action(self):
body = {"invalid_action": "None"}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.reserve_fixed_ip,
self.ip, body)
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index 360bcf7..cd3a4f1 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -79,18 +79,21 @@
return flavor['id']
@test.attr(type='gate')
+ @test.idempotent_id('8b4330e1-12c4-4554-9390-e6639971f086')
def test_create_flavor_with_int_id(self):
flavor_id = data_utils.rand_int_id(start=1000)
new_flavor_id = self._create_flavor(flavor_id)
self.assertEqual(new_flavor_id, str(flavor_id))
@test.attr(type='gate')
+ @test.idempotent_id('94c9bb4e-2c2a-4f3c-bb1f-5f0daf918e6d')
def test_create_flavor_with_uuid_id(self):
flavor_id = str(uuid.uuid4())
new_flavor_id = self._create_flavor(flavor_id)
self.assertEqual(new_flavor_id, flavor_id)
@test.attr(type='gate')
+ @test.idempotent_id('f83fe669-6758-448a-a85e-32d351f36fe0')
def test_create_flavor_with_none_id(self):
# If nova receives a request with None as flavor_id,
# nova generates flavor_id of uuid.
@@ -99,6 +102,7 @@
self.assertEqual(new_flavor_id, str(uuid.UUID(new_flavor_id)))
@test.attr(type='gate')
+ @test.idempotent_id('8261d7b0-be58-43ec-a2e5-300573c3f6c5')
def test_create_flavor_verify_entry_in_list_details(self):
# Create a flavor and ensure it's details are listed
# This operation requires the user to have 'admin' role
@@ -123,6 +127,7 @@
self.assertTrue(flag)
@test.attr(type='gate')
+ @test.idempotent_id('63dc64e6-2e79-4fdf-868f-85500d308d66')
def test_create_list_flavor_without_extra_data(self):
# Create a flavor and ensure it is listed
# This operation requires the user to have 'admin' role
@@ -164,6 +169,7 @@
self.assertTrue(flag)
@test.attr(type='gate')
+ @test.idempotent_id('be6cc18c-7c5d-48c0-ac16-17eaf03c54eb')
def test_list_non_public_flavor(self):
# Create a flavor with os-flavor-access:is_public false.
# The flavor should not be present in list_details as the
@@ -196,6 +202,7 @@
self.assertFalse(flag)
@test.attr(type='gate')
+ @test.idempotent_id('bcc418ef-799b-47cc-baa1-ce01368b8987')
def test_create_server_with_non_public_flavor(self):
# Create a flavor with os-flavor-access:is_public false
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -210,11 +217,12 @@
self.addCleanup(self.flavor_clean_up, flavor['id'])
# Verify flavor is not used by other user
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.os.servers_client.create_server,
'test', self.image_ref, flavor['id'])
@test.attr(type='gate')
+ @test.idempotent_id('b345b196-bfbd-4231-8ac1-6d7fe15ff3a3')
def test_list_public_flavor_with_other_user(self):
# Create a Flavor with public access.
# Try to List/Get flavor with another user
@@ -238,6 +246,7 @@
self.assertTrue(flag)
@test.attr(type='gate')
+ @test.idempotent_id('fb9cbde6-3a0e-41f2-a983-bdb0a823c44e')
def test_is_public_string_variations(self):
flavor_id_not_public = data_utils.rand_int_id(start=1000)
flavor_name_not_public = data_utils.rand_name(self.flavor_name_prefix)
@@ -280,6 +289,7 @@
flavor_name_public)
@test.attr(type='gate')
+ @test.idempotent_id('3b541a2e-2ac2-4b42-8b8d-ba6e22fcd4da')
def test_create_flavor_using_string_ram(self):
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
new_flavor_id = data_utils.rand_int_id(start=1000)
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 8a33ce7..aaa96ac 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -44,6 +44,7 @@
cls.disk = 10
@test.attr(type='gate')
+ @test.idempotent_id('ea2c2211-29fa-4db9-97c3-906d36fad3e0')
def test_flavor_access_list_with_private_flavor(self):
# Test to make sure that list flavor access on a newly created
# private flavor will return an empty access list
@@ -59,6 +60,7 @@
self.assertEqual(len(flavor_access), 0, str(flavor_access))
@test.attr(type='gate')
+ @test.idempotent_id('59e622f6-bdf6-45e3-8ba8-fedad905a6b4')
def test_flavor_access_add_remove(self):
# Test to add and remove flavor access to a given tenant.
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 4ba9eb2..af53985 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -43,6 +43,7 @@
cls.disk = 10
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0621c53e-d45d-40e7-951d-43e5e257b272')
def test_flavor_access_list_with_public_flavor(self):
# Test to list flavor access with exceptions by querying public flavor
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -53,11 +54,12 @@
new_flavor_id,
is_public='True')
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_flavor_access,
new_flavor_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('41eaaade-6d37-4f28-9c74-f21b46ca67bd')
def test_flavor_non_admin_add(self):
# Test to add flavor access as a user without admin privileges.
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -68,12 +70,13 @@
new_flavor_id,
is_public='False')
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.flavors_client.add_flavor_access,
new_flavor['id'],
self.tenant_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('073e79a6-c311-4525-82dc-6083d919cb3a')
def test_flavor_non_admin_remove(self):
# Test to remove flavor access as a user without admin privileges.
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -88,12 +91,13 @@
self.client.add_flavor_access(new_flavor['id'], self.tenant_id)
self.addCleanup(self.client.remove_flavor_access,
new_flavor['id'], self.tenant_id)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.flavors_client.remove_flavor_access,
new_flavor['id'],
self.tenant_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
def test_add_flavor_access_duplicate(self):
# Create a new flavor.
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -112,12 +116,13 @@
# An exception should be raised when adding flavor access to the same
# tenant
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.add_flavor_access,
new_flavor['id'],
self.tenant_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
def test_remove_flavor_access_not_found(self):
# Create a new flavor.
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -130,7 +135,7 @@
self.addCleanup(self.client.delete_flavor, new_flavor['id'])
# An exception should be raised when flavor access is not found
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.remove_flavor_access,
new_flavor['id'],
str(uuid.uuid4()))
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index 55c3358..5847a64 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -57,6 +57,7 @@
super(FlavorsExtraSpecsTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('0b2f9d4b-1ca2-4b99-bb40-165d4bb94208')
def test_flavor_set_get_update_show_unset_keys(self):
# Test to SET, GET, UPDATE, SHOW, UNSET flavor extra
# spec as a user with admin privileges.
@@ -87,6 +88,7 @@
self.client.unset_flavor_extra_spec(self.flavor['id'], "key2")
@test.attr(type='gate')
+ @test.idempotent_id('a99dad88-ae1c-4fba-aeb4-32f898218bd0')
def test_flavor_non_admin_get_all_keys(self):
specs = {"key1": "value1", "key2": "value2"}
self.client.set_flavor_extra_spec(self.flavor['id'], specs)
@@ -96,6 +98,7 @@
self.assertEqual(body[key], specs[key])
@test.attr(type='gate')
+ @test.idempotent_id('12805a7f-39a3-4042-b989-701d5cad9c90')
def test_flavor_non_admin_get_specific_key(self):
specs = {"key1": "value1", "key2": "value2"}
body = self.client.set_flavor_extra_spec(self.flavor['id'], specs)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index 2663e25..979fdd3 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -14,9 +14,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -58,22 +59,24 @@
super(FlavorsExtraSpecsNegativeTestJSON, cls).resource_cleanup()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a00a3b81-5641-45a8-ab2b-4a8ec41e1d7d')
def test_flavor_non_admin_set_keys(self):
# Test to SET flavor extra spec as a user without admin privileges.
specs = {"key1": "value1", "key2": "value2"}
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.flavors_client.set_flavor_extra_spec,
self.flavor['id'],
specs)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1ebf4ef8-759e-48fe-a801-d451d80476fb')
def test_flavor_non_admin_update_specific_key(self):
# non admin user is not allowed to update flavor extra spec
specs = {"key1": "value1", "key2": "value2"}
body = self.client.set_flavor_extra_spec(
self.flavor['id'], specs)
self.assertEqual(body['key1'], 'value1')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.flavors_client.
update_flavor_extra_spec,
self.flavor['id'],
@@ -81,43 +84,48 @@
key1='value1_new')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
def test_flavor_non_admin_unset_keys(self):
specs = {"key1": "value1", "key2": "value2"}
self.client.set_flavor_extra_spec(self.flavor['id'], specs)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.flavors_client.unset_flavor_extra_spec,
self.flavor['id'],
'key1')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
def test_flavor_unset_nonexistent_key(self):
nonexistent_key = data_utils.rand_name('flavor_key')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.unset_flavor_extra_spec,
self.flavor['id'],
nonexistent_key)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
def test_flavor_get_nonexistent_key(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.flavors_client.get_flavor_extra_spec_with_key,
self.flavor['id'],
"nonexistent_key")
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('25b822b8-9f49-44f6-80de-d99f0482e5cb')
def test_flavor_update_mismatch_key(self):
# the key will be updated should be match the key in the body
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_flavor_extra_spec,
self.flavor['id'],
"key2",
key1="value")
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f5889590-bf66-41cc-b4b1-6e6370cfd93f')
def test_flavor_update_more_key(self):
# there should be just one item in the request body
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_flavor_extra_spec,
self.flavor['id'],
"key1",
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index 86125fb..042c270 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -15,11 +15,12 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.api_schema.request.compute.v2 import flavors
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
@@ -52,6 +53,7 @@
cls.rxtx = 2
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('404451c0-c1ae-4448-8d50-d74f26f93ec8')
def test_get_flavor_details_for_deleted_flavor(self):
# Delete a flavor and ensure it is not listed
# Create a test flavor
@@ -83,21 +85,23 @@
self.assertTrue(flag)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6f56e7b7-7500-4d0c-9913-880ca1efed87')
def test_create_flavor_as_user(self):
# only admin user can create a flavor
flavor_name = data_utils.rand_name(self.flavor_name_prefix)
new_flavor_id = str(uuid.uuid4())
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.create_flavor,
flavor_name, self.ram, self.vcpus, self.disk,
new_flavor_id, ephemeral=self.ephemeral,
swap=self.swap, rxtx=self.rxtx)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a9a6dc02-8c14-4e05-a1ca-3468d4214882')
def test_delete_flavor_as_user(self):
# only admin user can delete a flavor
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.user_client.delete_flavor,
self.flavor_ref_alt)
@@ -105,6 +109,5 @@
@test.SimpleNegativeAutoTest
class FlavorCreateNegativeTestJSON(base.BaseV2ComputeAdminTest,
test.NegativeAutoTest):
- _interface = 'json'
_service = CONF.compute.catalog_type
_schema = flavors.flavor_create
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index c1263ea..7ca081a 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -40,7 +40,7 @@
@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()
+ body = cls.client.list_floating_ips_bulk()
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:
@@ -57,6 +57,7 @@
pass
@test.attr(type='gate')
+ @test.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
@test.services('network')
def test_create_list_delete_floating_ips_bulk(self):
# Create, List and delete the Floating IPs Bulk
@@ -65,18 +66,14 @@
# 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'
- resp, body = self.client.create_floating_ips_bulk(self.ip_range,
- pool,
- interface)
-
- self.assertEqual(200, resp.status)
+ body = self.client.create_floating_ips_bulk(self.ip_range,
+ pool,
+ interface)
self.addCleanup(self._delete_floating_ips_bulk, self.ip_range)
self.assertEqual(self.ip_range, body['ip_range'])
- resp, ips_list = self.client.list_floating_ips_bulk()
- self.assertEqual(200, resp.status)
+ ips_list = self.client.list_floating_ips_bulk()
self.assertNotEqual(0, len(ips_list))
for ip in netaddr.IPNetwork(self.ip_range).iter_hosts():
self.assertIn(str(ip), map(lambda x: x['address'], ips_list))
- resp, body = self.client.delete_floating_ips_bulk(self.ip_range)
- self.assertEqual(200, resp.status)
- self.assertEqual(self.ip_range, body)
+ body = self.client.delete_floating_ips_bulk(self.ip_range)
+ self.assertEqual(self.ip_range, body.data)
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index b9d47bb..bef5d1f 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -29,11 +29,13 @@
cls.client = cls.os_adm.hosts_client
@test.attr(type='gate')
+ @test.idempotent_id('9bfaf98d-e2cb-44b0-a07e-2558b2821e4f')
def test_list_hosts(self):
hosts = self.client.list_hosts()
self.assertTrue(len(hosts) >= 2, str(hosts))
@test.attr(type='gate')
+ @test.idempotent_id('5dc06f5b-d887-47a2-bb2a-67762ef3c6de')
def test_list_hosts_with_zone(self):
self.useFixture(fixtures.LockFixture('availability_zone'))
hosts = self.client.list_hosts()
@@ -45,6 +47,7 @@
self.assertIn(host, hosts)
@test.attr(type='gate')
+ @test.idempotent_id('9af3c171-fbf4-4150-a624-22109733c2a6')
def test_list_hosts_with_a_blank_zone(self):
# If send the request with a blank zone, the request will be successful
# and it will return all the hosts list
@@ -53,6 +56,7 @@
self.assertNotEqual(0, len(hosts))
@test.attr(type='gate')
+ @test.idempotent_id('c6ddbadb-c94e-4500-b12f-8ffc43843ff8')
def test_list_hosts_with_nonexistent_zone(self):
# If send the request with a nonexistent zone, the request will be
# successful and no hosts will be retured
@@ -61,6 +65,7 @@
self.assertEqual(0, len(hosts))
@test.attr(type='gate')
+ @test.idempotent_id('38adbb12-aee2-4498-8aec-329c72423aa4')
def test_show_host_detail(self):
hosts = self.client.list_hosts()
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index fc918a3..3c070ce 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -12,9 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -37,40 +38,45 @@
return hostname
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
def test_list_hosts_with_non_admin_user(self):
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_hosts)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
def test_show_host_detail_with_nonexistent_hostname(self):
nonexitent_hostname = data_utils.rand_name('rand_hostname')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.show_host_detail, nonexitent_hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
def test_show_host_detail_with_non_admin_user(self):
hostname = self._get_host_name()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.show_host_detail,
hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
def test_update_host_with_non_admin_user(self):
hostname = self._get_host_name()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.update_host,
hostname,
status='enable',
maintenance_mode='enable')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('76e396fe-5418-4dd3-a186-5b301edc0721')
def test_update_host_with_extra_param(self):
# only 'status' and 'maintenance_mode' are the valid params.
hostname = self._get_host_name()
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_host,
hostname,
status='enable',
@@ -78,90 +84,100 @@
param='XXX')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
def test_update_host_with_invalid_status(self):
# 'status' can only be 'enable' or 'disable'
hostname = self._get_host_name()
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_host,
hostname,
status='invalid',
maintenance_mode='enable')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
def test_update_host_with_invalid_maintenance_mode(self):
# 'maintenance_mode' can only be 'enable' or 'disable'
hostname = self._get_host_name()
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_host,
hostname,
status='enable',
maintenance_mode='invalid')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
def test_update_host_without_param(self):
# 'status' or 'maintenance_mode' needed for host update
hostname = self._get_host_name()
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_host,
hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
def test_update_nonexistent_host(self):
nonexitent_hostname = data_utils.rand_name('rand_hostname')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_host,
nonexitent_hostname,
status='enable',
maintenance_mode='enable')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
def test_startup_nonexistent_host(self):
nonexitent_hostname = data_utils.rand_name('rand_hostname')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.startup_host,
nonexitent_hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
def test_startup_host_with_non_admin_user(self):
hostname = self._get_host_name()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.startup_host,
hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
def test_shutdown_nonexistent_host(self):
nonexitent_hostname = data_utils.rand_name('rand_hostname')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.shutdown_host,
nonexitent_hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
def test_shutdown_host_with_non_admin_user(self):
hostname = self._get_host_name()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.shutdown_host,
hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
def test_reboot_nonexistent_host(self):
nonexitent_hostname = data_utils.rand_name('rand_hostname')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.reboot_host,
nonexitent_hostname)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
def test_reboot_host_with_non_admin_user(self):
hostname = self._get_host_name()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.reboot_host,
hostname)
diff --git a/tempest/api/compute/admin/test_hypervisor.py b/tempest/api/compute/admin/test_hypervisor.py
index fbfef87..c65bded 100644
--- a/tempest/api/compute/admin/test_hypervisor.py
+++ b/tempest/api/compute/admin/test_hypervisor.py
@@ -37,18 +37,21 @@
self.assertTrue(len(hypers) > 0, "No hypervisors found: %s" % hypers)
@test.attr(type='gate')
+ @test.idempotent_id('7f0ceacd-c64d-4e96-b8ee-d02943142cc5')
def test_get_hypervisor_list(self):
# List of hypervisor and available hypervisors hostname
hypers = self._list_hypervisors()
self.assertHypervisors(hypers)
@test.attr(type='gate')
+ @test.idempotent_id('1e7fdac2-b672-4ad1-97a4-bad0e3030118')
def test_get_hypervisor_list_details(self):
# Display the details of the all hypervisor
hypers = self.client.get_hypervisor_list_details()
self.assertHypervisors(hypers)
@test.attr(type='gate')
+ @test.idempotent_id('94ff9eae-a183-428e-9cdb-79fde71211cc')
def test_get_hypervisor_show_details(self):
# Display the details of the specified hypervisor
hypers = self._list_hypervisors()
@@ -60,6 +63,7 @@
hypers[0]['hypervisor_hostname'])
@test.attr(type='gate')
+ @test.idempotent_id('e81bba3f-6215-4e39-a286-d52d2f906862')
def test_get_hypervisor_show_servers(self):
# Show instances about the specific hypervisors
hypers = self._list_hypervisors()
@@ -70,12 +74,14 @@
self.assertTrue(len(hypervisors) > 0)
@test.attr(type='gate')
+ @test.idempotent_id('797e4f28-b6e0-454d-a548-80cc77c00816')
def test_get_hypervisor_stats(self):
# Verify the stats of the all hypervisor
stats = self.client.get_hypervisor_stats()
self.assertTrue(len(stats) > 0)
@test.attr(type='gate')
+ @test.idempotent_id('91a50d7d-1c2b-4f24-b55a-a1fe20efca70')
def test_get_hypervisor_uptime(self):
# Verify that GET shows the specified hypervisor uptime
hypers = self._list_hypervisors()
@@ -113,6 +119,7 @@
"None of the hypervisors had a valid uptime: %s" % hypers)
@test.attr(type='gate')
+ @test.idempotent_id('d7e1805b-3b14-4a3b-b6fd-50ec6d9f361f')
def test_search_hypervisor(self):
hypers = self._list_hypervisors()
self.assertHypervisors(hypers)
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index a137a61..556424a 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -39,97 +39,108 @@
return hypers
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
def test_show_nonexistent_hypervisor(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.client.get_hypervisor_show_details,
nonexistent_hypervisor_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
def test_show_hypervisor_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_show_details,
hypers[0]['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
def test_show_servers_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_servers,
hypers[0]['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('02463d69-0ace-4d33-a4a8-93d7883a2bba')
def test_show_servers_with_nonexistent_hypervisor(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.client.get_hypervisor_servers,
nonexistent_hypervisor_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e2b061bb-13f9-40d8-9d6e-d5bf17595849')
def test_get_hypervisor_stats_with_non_admin_user(self):
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_stats)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
def test_get_nonexistent_hypervisor_uptime(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.client.get_hypervisor_uptime,
nonexistent_hypervisor_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
def test_get_hypervisor_uptime_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_uptime,
hypers[0]['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('51b3d536-9b14-409c-9bce-c6f7c794994e')
def test_get_hypervisor_list_with_non_admin_user(self):
# List of hypervisor and available services with non admin user
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_list)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('dc02db05-e801-4c5f-bc8e-d915290ab345')
def test_get_hypervisor_list_details_with_non_admin_user(self):
# List of hypervisor details and available services with non admin user
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.get_hypervisor_list_details)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
def test_search_nonexistent_hypervisor(self):
nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.client.search_hypervisor,
nonexistent_hypervisor_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
def test_search_hypervisor_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.non_adm_client.search_hypervisor,
hypers[0]['hypervisor_hostname'])
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index f7b5e43..1a86b2d 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -28,10 +28,10 @@
cls.adm_client = cls.os_adm.instance_usages_audit_log_client
@test.attr(type='gate')
+ @test.idempotent_id('25319919-33d9-424f-9f99-2c203ee48b9d')
def test_list_instance_usage_audit_logs(self):
# list instance usage audit logs
- resp, body = self.adm_client.list_instance_usage_audit_logs()
- self.assertEqual(200, resp.status)
+ body = self.adm_client.list_instance_usage_audit_logs()
expected_items = ['total_errors', 'total_instances', 'log',
'num_hosts_running', 'num_hosts_done',
'num_hosts', 'hosts_not_run', 'overall_status',
@@ -41,13 +41,13 @@
self.assertIn(item, body)
@test.attr(type='gate')
+ @test.idempotent_id('6e40459d-7c5f-400b-9e83-449fbc8e7feb')
def test_get_instance_usage_audit_log(self):
# Get instance usage audit log before specified time
now = datetime.datetime.now()
- resp, body = self.adm_client.get_instance_usage_audit_log(
+ body = self.adm_client.get_instance_usage_audit_log(
urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
- self.assertEqual(200, resp.status)
expected_items = ['total_errors', 'total_instances', 'log',
'num_hosts_running', 'num_hosts_done', 'num_hosts',
'hosts_not_run', 'overall_status', 'period_ending',
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index c4905d9..6b5a82f 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -16,8 +16,9 @@
import datetime
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -29,19 +30,21 @@
cls.adm_client = cls.os_adm.instance_usages_audit_log_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a9d33178-d2c9-4131-ad3b-f4ca8d0308a2')
def test_instance_usage_audit_logs_with_nonadmin_user(self):
# the instance_usage_audit_logs API just can be accessed by admin user
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.instance_usages_audit_log_client.
list_instance_usage_audit_logs)
now = datetime.datetime.now()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.instance_usages_audit_log_client.
get_instance_usage_audit_log,
urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8')
def test_get_instance_usage_audit_logs_with_invalid_time(self):
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.adm_client.get_instance_usage_audit_log,
"invalid_time")
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 7ba05ef..67e4fe3 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -29,27 +29,26 @@
cls.client = cls.os_adm.migrations_client
@test.attr(type='gate')
+ @test.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
def test_list_migrations(self):
# Admin can get the migrations list
- resp, _ = self.client.list_migrations()
- self.assertEqual(200, resp.status)
+ self.client.list_migrations()
+ @test.idempotent_id('1b512062-8093-438e-b47a-37d2f597cd64')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='gate')
def test_list_migrations_in_flavor_resize_situation(self):
# Admin can get the migrations list which contains the resized server
- resp, server = self.create_test_server(wait_until="ACTIVE")
+ server = self.create_test_server(wait_until="ACTIVE")
server_id = server['id']
- resp, _ = self.servers_client.resize(server_id, self.flavor_ref_alt)
- self.assertEqual(202, resp.status)
+ self.servers_client.resize(server_id, self.flavor_ref_alt)
self.servers_client.wait_for_server_status(server_id, 'VERIFY_RESIZE')
self.servers_client.confirm_resize(server_id)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
- resp, body = self.client.list_migrations()
- self.assertEqual(200, resp.status)
+ body = self.client.list_migrations()
instance_uuids = [x['instance_uuid'] for x in body]
self.assertIn(server_id, instance_uuids)
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index 75f3199..fa72c01 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -15,6 +15,7 @@
from tempest.api.compute import base
from tempest import config
+from tempest import test
CONF = config.CONF
@@ -33,8 +34,9 @@
super(NetworksTest, cls).resource_setup()
cls.client = cls.os_adm.networks_client
+ @test.idempotent_id('d206d211-8912-486f-86e2-a9d090d1f416')
def test_get_network(self):
- resp, networks = self.client.list_networks()
+ networks = self.client.list_networks()
configured_network = [x for x in networks if x['label'] ==
CONF.compute.fixed_network_name]
self.assertEqual(1, len(configured_network),
@@ -42,11 +44,12 @@
len(configured_network),
CONF.compute.fixed_network_name))
configured_network = configured_network[0]
- _, network = self.client.get_network(configured_network['id'])
+ network = self.client.get_network(configured_network['id'])
self.assertEqual(configured_network['label'], network['label'])
+ @test.idempotent_id('df3d1046-6fa5-4b2c-ad0c-cfa46a351cb9')
def test_list_all_networks(self):
- _, networks = self.client.list_networks()
+ networks = self.client.list_networks()
# Check the configured network is in the list
configured_network = CONF.compute.fixed_network_name
self.assertIn(configured_network, [x['label'] for x in networks])
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index b0fcf94..35e682e 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -51,6 +51,7 @@
'cores', 'security_groups'))
@test.attr(type='smoke')
+ @test.idempotent_id('3b0a7c8f-cf58-46b8-a60c-715a32a8ba7d')
def test_get_default_quotas(self):
# Admin can get the default resource quota set for a tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -61,6 +62,7 @@
self.assertIn(quota, quota_set.keys())
@test.attr(type='gate')
+ @test.idempotent_id('55fbe2bf-21a9-435b-bbd2-4162b0ed799a')
def test_update_all_quota_resources_for_tenant(self):
# Admin can update all the resource quota limits for a tenant
default_quota_set = self.adm_client.get_default_quota_set(
@@ -92,6 +94,7 @@
# TODO(afazekas): merge these test cases
@test.attr(type='gate')
+ @test.idempotent_id('ce9e0815-8091-4abd-8345-7fe5b85faa1d')
def test_get_updated_quotas(self):
# Verify that GET shows the updated quota set of tenant
tenant_name = data_utils.rand_name('cpu_quota_tenant_')
@@ -125,6 +128,7 @@
self.assertEqual(2048, quota_set['ram'])
@test.attr(type='gate')
+ @test.idempotent_id('389d04f0-3a41-405f-9317-e5f86e3c44f0')
def test_delete_quota(self):
# Admin can delete the resource quota set for a tenant
tenant_name = data_utils.rand_name('ram_quota_tenant_')
@@ -169,6 +173,7 @@
# global state, and possibly needs to be part of a set of
# tests that get run all by themselves at the end under a
# 'danger' flag.
+ @test.idempotent_id('7932ab0f-5136-4075-b201-c0e2338df51a')
def test_update_default_quotas(self):
LOG.debug("get the current 'default' quota class values")
body = self.adm_client.get_quota_class_set('default')
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 7cefe90..73428df 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -13,11 +13,11 @@
# under the License.
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -38,8 +38,9 @@
cls.demo_tenant_id = cls.client.tenant_id
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
def test_update_quota_normal_user(self):
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.update_quota_set,
self.demo_tenant_id,
ram=0)
@@ -47,6 +48,7 @@
# TODO(afazekas): Add dedicated tenant to the skiped quota tests
# it can be moved into the setUpClass as well
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
def test_create_server_when_cpu_quota_is_full(self):
# Disallow server creation when tenant's vcpu quota is full
quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
@@ -59,10 +61,11 @@
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
cores=default_vcpu_quota)
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.create_test_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6fdd7012-584d-4327-a61c-49122e0d5864')
def test_create_server_when_memory_quota_is_full(self):
# Disallow server creation when tenant's memory quota is full
quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
@@ -75,10 +78,11 @@
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
ram=default_mem_quota)
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.create_test_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7c6be468-0274-449a-81c3-ac1c32ee0161')
def test_create_server_when_instances_quota_is_full(self):
# Once instances quota limit is reached, disallow server creation
quota_set = self.adm_client.get_quota_set(self.demo_tenant_id)
@@ -90,12 +94,13 @@
instances=instances_quota)
self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
instances=default_instances_quota)
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.create_test_server)
@decorators.skip_because(bug="1186354",
condition=CONF.service_available.neutron)
@test.attr(type='gate')
+ @test.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
@test.services('network')
def test_security_groups_exceed_limit(self):
# Negative test: Creation Security Groups over limit should FAIL
@@ -116,13 +121,14 @@
# Check we cannot create anymore
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.sg_client.create_security_group,
"sg-overlimit", "sg-desc")
@decorators.skip_because(bug="1186354",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
@test.services('network')
def test_security_groups_rules_exceed_limit(self):
# Negative test: Creation of Security Group Rules should FAIL
@@ -155,6 +161,6 @@
# Check we cannot create SG rule anymore
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
- self.assertRaises((exceptions.OverLimit, exceptions.Unauthorized),
+ self.assertRaises((lib_exc.OverLimit, lib_exc.Unauthorized),
self.sg_client.create_security_group_rule,
secgroup_id, ip_protocol, 1025, 1025)
diff --git a/tempest/api/compute/admin/test_security_group_default_rules.py b/tempest/api/compute/admin/test_security_group_default_rules.py
index 563d517..87c0008 100644
--- a/tempest/api/compute/admin/test_security_group_default_rules.py
+++ b/tempest/api/compute/admin/test_security_group_default_rules.py
@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.api.compute import base
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -30,10 +30,14 @@
@testtools.skipIf(CONF.service_available.neutron,
"Skip as this functionality is not yet "
"implemented in Neutron. Related Bug#1311500")
- def resource_setup(cls):
+ def setup_credentials(cls):
# A network and a subnet will be created for these tests
cls.set_network_resources(network=True, subnet=True)
- super(SecurityGroupDefaultRulesTest, cls).resource_setup()
+ super(SecurityGroupDefaultRulesTest, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(SecurityGroupDefaultRulesTest, cls).setup_clients()
cls.adm_client = cls.os_adm.security_group_default_rules_client
def _create_security_group_default_rules(self, ip_protocol='tcp',
@@ -52,6 +56,7 @@
return rule
@test.attr(type='smoke')
+ @test.idempotent_id('6d880615-eec3-4d29-97c5-7a074dde239d')
def test_create_delete_security_group_default_rules(self):
# Create and delete Security Group default rule
ip_protocols = ['tcp', 'udp', 'icmp']
@@ -59,11 +64,12 @@
rule = self._create_security_group_default_rules(ip_protocol)
# Delete Security Group default rule
self.adm_client.delete_security_group_default_rule(rule['id'])
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.adm_client.get_security_group_default_rule,
rule['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('4d752e0a-33a1-4c3a-b498-ff8667ca22e5')
def test_create_security_group_default_rule_without_cidr(self):
ip_protocol = 'udp'
from_port = 80
@@ -78,6 +84,7 @@
self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
@test.attr(type='smoke')
+ @test.idempotent_id('29f2d218-69b0-4a95-8f3d-6bd0ef732b3a')
def test_create_security_group_default_rule_with_blank_cidr(self):
ip_protocol = 'icmp'
from_port = 10
@@ -94,6 +101,7 @@
self.assertEqual('0.0.0.0/0', rule['ip_range']['cidr'])
@test.attr(type='smoke')
+ @test.idempotent_id('6e6de55e-9146-4ae0-89f2-3569586e0b9b')
def test_security_group_default_rules_list(self):
ip_protocol = 'tcp'
from_port = 22
@@ -110,6 +118,7 @@
self.assertIn(rule, rules)
@test.attr(type='smoke')
+ @test.idempotent_id('15cbb349-86b4-4f71-a048-04b7ef3f150b')
def test_default_security_group_default_rule_show(self):
ip_protocol = 'tcp'
from_port = 22
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 82cb26e..19f5b8c 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -37,6 +37,7 @@
else:
self.client.delete_security_group(securitygroup_id)
+ @test.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
@testtools.skipIf(CONF.service_available.neutron,
"Skipped because neutron do not support all_tenants"
"search filter.")
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index cff9a43..adeb64b 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -35,33 +35,34 @@
cls.flavors_client = cls.os_adm.flavors_client
cls.s1_name = data_utils.rand_name('server')
- resp, server = cls.create_test_server(name=cls.s1_name,
- wait_until='ACTIVE')
+ server = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
cls.s1_id = server['id']
cls.s2_name = data_utils.rand_name('server')
- resp, server = cls.create_test_server(name=cls.s2_name,
- wait_until='ACTIVE')
+ server = cls.create_test_server(name=cls.s2_name,
+ wait_until='ACTIVE')
cls.s2_id = server['id']
@test.attr(type='gate')
+ @test.idempotent_id('51717b38-bdc1-458b-b636-1cf82d99f62f')
def test_list_servers_by_admin(self):
# Listing servers by admin user returns empty list by default
- resp, body = self.client.list_servers_with_detail()
+ body = self.client.list_servers_with_detail()
servers = body['servers']
- self.assertEqual('200', resp['status'])
self.assertEqual([], servers)
@test.attr(type='gate')
+ @test.idempotent_id('06f960bb-15bb-48dc-873d-f96e89be7870')
def test_list_servers_filter_by_error_status(self):
# Filter the list of servers by server error status
params = {'status': 'error'}
- resp, server = self.client.reset_state(self.s1_id, state='error')
- resp, body = self.non_admin_client.list_servers(params)
+ self.client.reset_state(self.s1_id, state='error')
+ body = self.non_admin_client.list_servers(params)
# Reset server's state to 'active'
- resp, server = self.client.reset_state(self.s1_id, state='active')
+ self.client.reset_state(self.s1_id, state='active')
# Verify server's state
- resp, server = self.client.get_server(self.s1_id)
+ server = self.client.get_server(self.s1_id)
self.assertEqual(server['status'], 'ACTIVE')
servers = body['servers']
# Verify error server in list result
@@ -69,11 +70,12 @@
self.assertNotIn(self.s2_id, map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('9f5579ae-19b4-4985-a091-2a5d56106580')
def test_list_servers_by_admin_with_all_tenants(self):
# Listing servers by admin user with all tenants parameter
# Here should be listed all servers
params = {'all_tenants': ''}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
servers_name = map(lambda x: x['name'], servers)
@@ -81,74 +83,70 @@
self.assertIn(self.s2_name, servers_name)
@test.attr(type='gate')
+ @test.idempotent_id('7e5d6b8f-454a-4ba1-8ae2-da857af8338b')
def test_list_servers_by_admin_with_specified_tenant(self):
# In nova v2, tenant_id is ignored unless all_tenants is specified
# List the primary tenant but get nothing due to odd specified behavior
tenant_id = self.non_admin_client.tenant_id
params = {'tenant_id': tenant_id}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
self.assertEqual([], servers)
# List the admin tenant which has no servers
admin_tenant_id = self.client.tenant_id
params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
self.assertEqual([], servers)
@test.attr(type='gate')
+ @test.idempotent_id('86c7a8f7-50cf-43a9-9bac-5b985317134f')
def test_list_servers_filter_by_exist_host(self):
# Filter the list of servers by existent host
name = data_utils.rand_name('server')
flavor = self.flavor_ref
image_id = self.image_ref
- resp, test_server = self.client.create_server(
- name, image_id, flavor)
- self.assertEqual('202', resp['status'])
+ test_server = self.client.create_server(name, image_id, flavor)
self.addCleanup(self.client.delete_server, test_server['id'])
self.client.wait_for_server_status(test_server['id'], 'ACTIVE')
- resp, server = self.client.get_server(test_server['id'])
+ server = self.client.get_server(test_server['id'])
self.assertEqual(server['status'], 'ACTIVE')
hostname = server[self._host_key]
params = {'host': hostname}
- resp, body = self.client.list_servers(params)
- self.assertEqual('200', resp['status'])
+ body = self.client.list_servers(params)
servers = body['servers']
nonexistent_params = {'host': 'nonexistent_host'}
- resp, nonexistent_body = self.client.list_servers(
- nonexistent_params)
- self.assertEqual('200', resp['status'])
+ nonexistent_body = self.client.list_servers(nonexistent_params)
nonexistent_servers = nonexistent_body['servers']
self.assertIn(test_server['id'], map(lambda x: x['id'], servers))
self.assertNotIn(test_server['id'],
map(lambda x: x['id'], nonexistent_servers))
@test.attr(type='gate')
+ @test.idempotent_id('ee8ae470-db70-474d-b752-690b7892cab1')
def test_reset_state_server(self):
# Reset server's state to 'error'
- resp, server = self.client.reset_state(self.s1_id)
- self.assertEqual(202, resp.status)
+ self.client.reset_state(self.s1_id)
# Verify server's state
- resp, server = self.client.get_server(self.s1_id)
+ server = self.client.get_server(self.s1_id)
self.assertEqual(server['status'], 'ERROR')
# Reset server's state to 'active'
- resp, server = self.client.reset_state(self.s1_id, state='active')
- self.assertEqual(202, resp.status)
+ self.client.reset_state(self.s1_id, state='active')
# Verify server's state
- resp, server = self.client.get_server(self.s1_id)
+ server = self.client.get_server(self.s1_id)
self.assertEqual(server['status'], 'ACTIVE')
@test.attr(type='gate')
@decorators.skip_because(bug="1240043")
+ @test.idempotent_id('31ff3486-b8a0-4f56-a6c0-aab460531db3')
def test_get_server_diagnostics_by_admin(self):
# Retrieve server diagnostics by admin user
- resp, diagnostic = self.client.get_server_diagnostics(self.s1_id)
- self.assertEqual(200, resp.status)
+ diagnostic = self.client.get_server_diagnostics(self.s1_id)
basic_attrs = ['rx_packets', 'rx_errors', 'rx_drop',
'tx_packets', 'tx_errors', 'tx_drop',
'read_req', 'write_req', 'cpu', 'memory']
@@ -156,14 +154,14 @@
self.assertIn(key, str(diagnostic.keys()))
@test.attr(type='gate')
+ @test.idempotent_id('682cb127-e5bb-4f53-87ce-cb9003604442')
def test_rebuild_server_in_error_state(self):
# The server in error state should be rebuilt using the provided
# image and changed to ACTIVE state
# resetting vm state require admin privilege
- resp, server = self.client.reset_state(self.s1_id, state='error')
- self.assertEqual(202, resp.status)
- resp, rebuilt_server = self.non_admin_client.rebuild(
+ self.client.reset_state(self.s1_id, state='error')
+ rebuilt_server = self.non_admin_client.rebuild(
self.s1_id, self.image_ref_alt)
self.addCleanup(self.non_admin_client.wait_for_server_status,
self.s1_id, 'ACTIVE')
@@ -179,26 +177,25 @@
'ACTIVE',
raise_on_error=False)
# Verify the server properties after rebuilding
- resp, server = self.non_admin_client.get_server(rebuilt_server['id'])
+ server = self.non_admin_client.get_server(rebuilt_server['id'])
rebuilt_image_id = server['image']['id']
self.assertEqual(self.image_ref_alt, rebuilt_image_id)
@test.attr(type='gate')
+ @test.idempotent_id('7a1323b4-a6a2-497a-96cb-76c07b945c71')
def test_reset_network_inject_network_info(self):
# Reset Network of a Server
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, server_body = self.client.reset_network(server['id'])
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.reset_network(server['id'])
# Inject the Network Info into Server
- resp, server_body = self.client.inject_network_info(server['id'])
- self.assertEqual(202, resp.status)
+ self.client.inject_network_info(server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('fdcd9b33-0903-4e00-a1f7-b5f6543068d6')
def test_create_server_with_scheduling_hint(self):
# Create a server with scheduler hints.
hints = {
'same_host': self.s1_id
}
- resp, server = self.create_test_server(sched_hints=hints,
- wait_until='ACTIVE')
- self.assertEqual('202', resp['status'])
+ self.create_test_server(sched_hints=hints,
+ wait_until='ACTIVE')
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 0dddc76..cafbf81 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -14,13 +14,13 @@
import uuid
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -41,8 +41,8 @@
cls.tenant_id = cls.client.tenant_id
cls.s1_name = data_utils.rand_name('server')
- resp, server = cls.create_test_server(name=cls.s1_name,
- wait_until='ACTIVE')
+ server = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
cls.s1_id = server['id']
def _get_unused_flavor_id(self):
@@ -50,11 +50,12 @@
while True:
try:
self.flavors_client.get_flavor_details(flavor_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
break
flavor_id = data_utils.rand_int_id(start=1000)
return flavor_id
+ @test.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type=['negative', 'gate'])
@@ -71,11 +72,12 @@
ram, vcpus, disk,
flavor_id)
self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.client.resize,
self.servers[0]['id'],
flavor_ref['id'])
+ @test.idempotent_id('7368a427-2f26-4ad9-9ba9-911a0ec2b0db')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type=['negative', 'gate'])
@@ -92,42 +94,48 @@
ram, vcpus, disk,
flavor_id)
self.addCleanup(self.flavors_client.delete_flavor, flavor_id)
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.client.resize,
self.servers[0]['id'],
flavor_ref['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b0b4d8af-1256-41ef-9ee7-25f1c19dde80')
def test_reset_state_server_invalid_state(self):
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.reset_state, self.s1_id,
state='invalid')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4cdcc984-fab0-4577-9a9d-6d558527ee9d')
def test_reset_state_server_invalid_type(self):
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.reset_state, self.s1_id,
state=1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e741298b-8df2-46f0-81cb-8f814ff2504c')
def test_reset_state_server_nonexistent_server(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.reset_state, '999')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e84e2234-60d2-42fa-8b30-e2d3049724ac')
def test_get_server_diagnostics_by_non_admin(self):
# Non-admin user can not view server diagnostics according to policy
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_adm_client.get_server_diagnostics,
self.s1_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('46a4e1ca-87ae-4d28-987a-1b6b136a0221')
def test_migrate_non_existent_server(self):
# migrate a non existent server
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.migrate_server,
str(uuid.uuid4()))
+ @test.idempotent_id('b0b17f83-d14e-4fc4-8f31-bcc9f3cfa629')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
@@ -135,14 +143,12 @@
@test.attr(type=['negative', 'gate'])
def test_migrate_server_invalid_state(self):
# create server.
- resp, server = self.create_test_server(wait_until='ACTIVE')
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(wait_until='ACTIVE')
server_id = server['id']
# suspend the server.
- resp, _ = self.client.suspend_server(server_id)
- self.assertEqual(202, resp.status)
+ self.client.suspend_server(server_id)
self.client.wait_for_server_status(server_id, 'SUSPENDED')
# migrate an suspended server should fail
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.migrate_server,
server_id)
diff --git a/tempest/api/compute/admin/test_services.py b/tempest/api/compute/admin/test_services.py
index 5cf4a31..a6f79aa 100644
--- a/tempest/api/compute/admin/test_services.py
+++ b/tempest/api/compute/admin/test_services.py
@@ -30,11 +30,13 @@
cls.client = cls.os_adm.services_client
@test.attr(type='gate')
+ @test.idempotent_id('5be41ef4-53d1-41cc-8839-5c2a48a1b283')
def test_list_services(self):
services = self.client.list_services()
self.assertNotEqual(0, len(services))
@test.attr(type='gate')
+ @test.idempotent_id('f345b1ec-bc6e-4c38-a527-3ca2bc00bef5')
def test_get_service_by_service_binary_name(self):
binary_name = 'nova-compute'
params = {'binary': binary_name}
@@ -44,6 +46,7 @@
self.assertEqual(binary_name, service['binary'])
@test.attr(type='gate')
+ @test.idempotent_id('affb42d5-5b4b-43c8-8b0b-6dca054abcca')
def test_get_service_by_host_name(self):
services = self.client.list_services()
host_name = services[0]['host']
@@ -63,6 +66,7 @@
self.assertEqual(sorted(s1), sorted(s2))
@test.attr(type='gate')
+ @test.idempotent_id('39397f6f-37b8-4234-8671-281e44c74025')
def test_get_service_by_service_and_host_name(self):
services = self.client.list_services()
host_name = services[0]['host']
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index bb19a39..b8974ca 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -30,11 +31,13 @@
cls.non_admin_client = cls.services_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1126d1f8-266e-485f-a687-adc547492646')
def test_list_services_with_non_admin_user(self):
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_services)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d0884a69-f693-4e79-a9af-232d15643bf7')
def test_get_service_by_invalid_params(self):
# return all services if send the request with invalid parameter
services = self.client.list_services()
@@ -43,6 +46,7 @@
self.assertEqual(len(services), len(services_xxx))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1e966d4a-226e-47c7-b601-0b18a27add54')
def test_get_service_by_invalid_service_and_valid_host(self):
services = self.client.list_services()
host_name = services[0]['host']
@@ -51,6 +55,7 @@
self.assertEqual(0, len(services))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('64e7e7fb-69e8-4cb6-a71d-8d5eb0c98655')
def test_get_service_with_valid_service_and_invalid_host(self):
services = self.client.list_services()
binary_name = services[0]['binary']
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index f6553b3..be62b1d 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -30,7 +30,7 @@
cls.tenant_id = cls.client.tenant_id
# Create a server in the demo tenant
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ cls.create_test_server(wait_until='ACTIVE')
time.sleep(2)
now = datetime.datetime.now()
@@ -43,33 +43,33 @@
return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
@test.attr(type='gate')
+ @test.idempotent_id('062c8ae9-9912-4249-8b51-e38d664e926e')
def test_list_usage_all_tenants(self):
# Get usage for all tenants
params = {'start': self.start,
'end': self.end,
'detailed': int(bool(True))}
- resp, tenant_usage = self.adm_client.list_tenant_usages(params)
- self.assertEqual(200, resp.status)
+ tenant_usage = self.adm_client.list_tenant_usages(params)
self.assertEqual(len(tenant_usage), 8)
@test.attr(type='gate')
+ @test.idempotent_id('94135049-a4c5-4934-ad39-08fa7da4f22e')
def test_get_usage_tenant(self):
# Get usage for a specific tenant
params = {'start': self.start,
'end': self.end}
- resp, tenant_usage = self.adm_client.get_tenant_usage(
+ tenant_usage = self.adm_client.get_tenant_usage(
self.tenant_id, params)
- self.assertEqual(200, resp.status)
self.assertEqual(len(tenant_usage), 8)
@test.attr(type='gate')
+ @test.idempotent_id('9d00a412-b40e-4fd9-8eba-97b496316116')
def test_get_usage_tenant_with_non_admin_user(self):
# Get usage for a specific tenant with non admin user
params = {'start': self.start,
'end': self.end}
- resp, tenant_usage = self.client.get_tenant_usage(
+ tenant_usage = self.client.get_tenant_usage(
self.tenant_id, params)
- self.assertEqual(200, resp.status)
self.assertEqual(len(tenant_usage), 8)
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
index 8c31d7c..8801e85 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -14,9 +14,9 @@
# under the License.
import datetime
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -38,28 +38,31 @@
return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8b21e135-d94b-4991-b6e9-87059609c8ed')
def test_get_usage_tenant_with_empty_tenant_id(self):
# Get usage for a specific tenant empty
params = {'start': self.start,
'end': self.end}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.adm_client.get_tenant_usage,
'', params)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4079dd2a-9e8d-479f-869d-6fa985ce45b6')
def test_get_usage_tenant_with_invalid_date(self):
# Get usage for tenant with invalid date
params = {'start': self.end,
'end': self.start}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.adm_client.get_tenant_usage,
self.client.tenant_id, params)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bbe6fe2c-15d8-404c-a0a2-44fad0ad5cc7')
def test_list_usage_all_tenants_with_non_admin_user(self):
# Get usage for all tenants with non admin user
params = {'start': self.start,
'end': self.end,
'detailed': int(bool(True))}
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.list_tenant_usages, params)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 3e80bf2..89818b1 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -13,9 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import time
from tempest import clients
+from tempest.common import credentials
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -35,15 +37,60 @@
force_tenant_isolation = False
@classmethod
- def resource_setup(cls):
- cls.set_network_resources()
- super(BaseComputeTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(BaseComputeTest, cls).skip_checks()
+ if cls._api_version != 2:
+ msg = ("Unexpected API version is specified (%s)" %
+ cls._api_version)
+ raise exceptions.InvalidConfiguration(message=msg)
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources()
+ super(BaseComputeTest, cls).setup_credentials()
# TODO(andreaf) WE should care also for the alt_manager here
# but only once client lazy load in the manager is done
cls.os = cls.get_client_manager()
+ # Note that we put this here and not in skip_checks because in
+ # the case of preprovisioned users we won't know if we can get
+ # two distinct users until we go and lock them
cls.multi_user = cls.check_multi_user()
+ @classmethod
+ def setup_clients(cls):
+ super(BaseComputeTest, cls).setup_clients()
+ cls.servers_client = cls.os.servers_client
+ cls.flavors_client = cls.os.flavors_client
+ cls.images_client = cls.os.images_client
+ cls.extensions_client = cls.os.extensions_client
+ cls.floating_ips_client = cls.os.floating_ips_client
+ cls.keypairs_client = cls.os.keypairs_client
+ cls.security_groups_client = cls.os.security_groups_client
+ cls.quotas_client = cls.os.quotas_client
+ # NOTE(mriedem): os-quota-class-sets is v2 API only
+ cls.quota_classes_client = cls.os.quota_classes_client
+ # NOTE(mriedem): os-networks is v2 API only
+ cls.networks_client = cls.os.networks_client
+ cls.limits_client = cls.os.limits_client
+ cls.volumes_extensions_client = cls.os.volumes_extensions_client
+ cls.volumes_client = cls.os.volumes_client
+ cls.interfaces_client = cls.os.interfaces_client
+ cls.fixed_ips_client = cls.os.fixed_ips_client
+ cls.availability_zone_client = cls.os.availability_zone_client
+ cls.agents_client = cls.os.agents_client
+ cls.aggregates_client = cls.os.aggregates_client
+ cls.services_client = cls.os.services_client
+ cls.instance_usages_audit_log_client = (
+ cls.os.instance_usages_audit_log_client)
+ cls.hypervisor_client = cls.os.hypervisor_client
+ cls.certificates_client = cls.os.certificates_client
+ cls.migrations_client = cls.os.migrations_client
+ cls.security_group_default_rules_client = (
+ cls.os.security_group_default_rules_client)
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseComputeTest, cls).resource_setup()
cls.build_interval = CONF.compute.build_interval
cls.build_timeout = CONF.compute.build_timeout
cls.ssh_user = CONF.compute.ssh_user
@@ -58,39 +105,13 @@
cls.security_groups = []
cls.server_groups = []
- if cls._api_version == 2:
- cls.servers_client = cls.os.servers_client
- cls.flavors_client = cls.os.flavors_client
- cls.images_client = cls.os.images_client
- cls.extensions_client = cls.os.extensions_client
- cls.floating_ips_client = cls.os.floating_ips_client
- cls.keypairs_client = cls.os.keypairs_client
- cls.security_groups_client = cls.os.security_groups_client
- cls.quotas_client = cls.os.quotas_client
- # NOTE(mriedem): os-quota-class-sets is v2 API only
- cls.quota_classes_client = cls.os.quota_classes_client
- # NOTE(mriedem): os-networks is v2 API only
- cls.networks_client = cls.os.networks_client
- cls.limits_client = cls.os.limits_client
- cls.volumes_extensions_client = cls.os.volumes_extensions_client
- cls.volumes_client = cls.os.volumes_client
- cls.interfaces_client = cls.os.interfaces_client
- cls.fixed_ips_client = cls.os.fixed_ips_client
- cls.availability_zone_client = cls.os.availability_zone_client
- cls.agents_client = cls.os.agents_client
- cls.aggregates_client = cls.os.aggregates_client
- cls.services_client = cls.os.services_client
- cls.instance_usages_audit_log_client = \
- cls.os.instance_usages_audit_log_client
- cls.hypervisor_client = cls.os.hypervisor_client
- cls.certificates_client = cls.os.certificates_client
- cls.migrations_client = cls.os.migrations_client
- cls.security_group_default_rules_client = (
- cls.os.security_group_default_rules_client)
- else:
- msg = ("Unexpected API version is specified (%s)" %
- cls._api_version)
- raise exceptions.InvalidConfiguration(message=msg)
+ @classmethod
+ def resource_cleanup(cls):
+ cls.clear_images()
+ cls.clear_servers()
+ cls.clear_security_groups()
+ cls.clear_server_groups()
+ super(BaseComputeTest, cls).resource_cleanup()
@classmethod
def check_multi_user(cls):
@@ -107,7 +128,7 @@
for server in cls.servers:
try:
cls.servers_client.delete_server(server['id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# Something else already cleaned up the server, nothing to be
# worried about
pass
@@ -147,7 +168,7 @@
for image_id in cls.images:
try:
cls.images_client.delete_image(image_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# The image may have already been deleted which is OK.
pass
except Exception:
@@ -160,7 +181,7 @@
for sg in cls.security_groups:
try:
cls.security_groups_client.delete_security_group(sg['id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# The security group may have already been deleted which is OK.
pass
except Exception as exc:
@@ -174,7 +195,7 @@
for server_group_id in cls.server_groups:
try:
cls.servers_client.delete_server_group(server_group_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# The server-group may have already been deleted which is OK.
pass
except Exception:
@@ -182,14 +203,6 @@
server_group_id)
@classmethod
- def resource_cleanup(cls):
- cls.clear_images()
- cls.clear_servers()
- cls.clear_security_groups()
- cls.clear_server_groups()
- super(BaseComputeTest, cls).resource_cleanup()
-
- @classmethod
def create_test_server(cls, **kwargs):
"""Wrapper utility that returns a test server."""
name = data_utils.rand_name(cls.__name__ + "-instance")
@@ -198,14 +211,14 @@
flavor = kwargs.get('flavor', cls.flavor_ref)
image_id = kwargs.get('image_id', cls.image_ref)
- resp, body = cls.servers_client.create_server(
+ body = cls.servers_client.create_server(
name, image_id, flavor, **kwargs)
# handle the case of multiple servers
servers = [body]
if 'min_count' in kwargs or 'max_count' in kwargs:
# Get servers created which name match with name param.
- r, b = cls.servers_client.list_servers()
+ b = cls.servers_client.list_servers()
servers = [s for s in b['servers'] if s['name'].startswith(name)]
if 'wait_until' in kwargs:
@@ -226,7 +239,7 @@
cls.servers.extend(servers)
- return resp, body
+ return body
@classmethod
def create_security_group(cls, name=None, description=None):
@@ -247,9 +260,9 @@
name = data_utils.rand_name(cls.__name__ + "-Server-Group")
if policy is None:
policy = ['affinity']
- resp, body = cls.servers_client.create_server_group(name, policy)
+ body = cls.servers_client.create_server_group(name, policy)
cls.server_groups.append(body['id'])
- return resp, body
+ return body
def wait_for(self, condition):
"""Repeatedly calls condition() until a timeout."""
@@ -274,7 +287,7 @@
# TODO(mriedem): We should move the wait_for_resource_deletion
# into the delete_volume method as a convenience to the caller.
volumes_client.wait_for_resource_deletion(volume_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn("Unable to delete volume '%s' since it was not found. "
"Maybe it was already deleted?" % volume_id)
@@ -316,7 +329,7 @@
cls.servers_client.wait_for_server_termination(server_id)
except Exception:
LOG.exception('Failed to delete server %s' % server_id)
- resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
+ server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
cls.password = server['adminPass']
return server['id']
@@ -328,24 +341,27 @@
class BaseV2ComputeTest(BaseComputeTest):
_api_version = 2
- _interface = "json"
class BaseComputeAdminTest(BaseComputeTest):
"""Base test case class for Compute Admin API tests."""
- _interface = "json"
@classmethod
- def resource_setup(cls):
- super(BaseComputeAdminTest, cls).resource_setup()
- try:
- creds = cls.isolated_creds.get_admin_creds()
- cls.os_adm = clients.Manager(
- credentials=creds, interface=cls._interface)
- except NotImplementedError:
- msg = ("Missing Compute Admin API credentials in configuration.")
+ def skip_checks(cls):
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
raise cls.skipException(msg)
+ super(BaseComputeAdminTest, cls).skip_checks()
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseComputeAdminTest, cls).setup_credentials()
+ creds = cls.isolated_creds.get_admin_creds()
+ cls.os_adm = clients.Manager(credentials=creds)
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseComputeAdminTest, cls).setup_clients()
cls.availability_zone_admin_client = (
cls.os_adm.availability_zone_client)
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 15ccf53..2be201a 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -22,16 +22,17 @@
_api_version = 2
@test.attr(type='gate')
+ @test.idempotent_id('c070a441-b08e-447e-a733-905909535b1b')
def test_create_root_certificate(self):
# create certificates
- resp, body = self.certificates_client.create_certificate()
+ body = self.certificates_client.create_certificate()
self.assertIn('data', body)
self.assertIn('private_key', body)
@test.attr(type='gate')
+ @test.idempotent_id('3ac273d0-92d2-4632-bdfc-afbc21d4606c')
def test_get_root_certificate(self):
# get the root certificate
- resp, body = self.certificates_client.get_certificate('root')
- self.assertEqual(200, resp.status)
+ body = self.certificates_client.get_certificate('root')
self.assertIn('data', body)
self.assertIn('private_key', body)
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index c91ce17..b9056c7 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -29,6 +29,7 @@
cls.client = cls.flavors_client
@test.attr(type='smoke')
+ @test.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
def test_list_flavors(self):
# List of all flavors should contain the expected flavor
flavors = self.client.list_flavors()
@@ -38,6 +39,7 @@
self.assertIn(flavor_min_detail, flavors)
@test.attr(type='smoke')
+ @test.idempotent_id('6e85fde4-b3cd-4137-ab72-ed5f418e8c24')
def test_list_flavors_with_detail(self):
# Detailed list of all flavors should contain the expected flavor
flavors = self.client.list_flavors_with_detail()
@@ -45,12 +47,14 @@
self.assertIn(flavor, flavors)
@test.attr(type='smoke')
+ @test.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
def test_get_flavor(self):
# The expected flavor details should be returned
flavor = self.client.get_flavor_details(self.flavor_ref)
self.assertEqual(self.flavor_ref, flavor['id'])
@test.attr(type='gate')
+ @test.idempotent_id('8d7691b3-6ed4-411a-abc9-2839a765adab')
def test_list_flavors_limit_results(self):
# Only the expected number of flavors should be returned
params = {'limit': 1}
@@ -58,6 +62,7 @@
self.assertEqual(1, len(flavors))
@test.attr(type='gate')
+ @test.idempotent_id('b26f6327-2886-467a-82be-cef7a27709cb')
def test_list_flavors_detailed_limit_results(self):
# Only the expected number of flavors (detailed) should be returned
params = {'limit': 1}
@@ -65,6 +70,7 @@
self.assertEqual(1, len(flavors))
@test.attr(type='gate')
+ @test.idempotent_id('e800f879-9828-4bd0-8eae-4f17189951fb')
def test_list_flavors_using_marker(self):
# The list of flavors should start from the provided marker
flavor = self.client.get_flavor_details(self.flavor_ref)
@@ -76,6 +82,7 @@
'The list of flavors did not start after the marker.')
@test.attr(type='gate')
+ @test.idempotent_id('6db2f0c0-ddee-4162-9c84-0703d3dd1107')
def test_list_flavors_detailed_using_marker(self):
# The list of flavors should start from the provided marker
flavor = self.client.get_flavor_details(self.flavor_ref)
@@ -87,6 +94,7 @@
'The list of flavors did not start after the marker.')
@test.attr(type='gate')
+ @test.idempotent_id('3df2743e-3034-4e57-a4cb-b6527f6eac79')
def test_list_flavors_detailed_filter_by_min_disk(self):
# The detailed list of flavors should be filtered by disk space
flavor = self.client.get_flavor_details(self.flavor_ref)
@@ -97,6 +105,7 @@
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
@test.attr(type='gate')
+ @test.idempotent_id('09fe7509-b4ee-4b34-bf8b-39532dc47292')
def test_list_flavors_detailed_filter_by_min_ram(self):
# The detailed list of flavors should be filtered by RAM
flavor = self.client.get_flavor_details(self.flavor_ref)
@@ -107,6 +116,7 @@
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
@test.attr(type='gate')
+ @test.idempotent_id('10645a4d-96f5-443f-831b-730711e11dd4')
def test_list_flavors_filter_by_min_disk(self):
# The list of flavors should be filtered by disk space
flavor = self.client.get_flavor_details(self.flavor_ref)
@@ -117,6 +127,7 @@
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
@test.attr(type='gate')
+ @test.idempotent_id('935cf550-e7c8-4da6-8002-00f92d5edfaa')
def test_list_flavors_filter_by_min_ram(self):
# The list of flavors should be filtered by RAM
flavor = self.client.get_flavor_details(self.flavor_ref)
diff --git a/tempest/api/compute/floating_ips/base.py b/tempest/api/compute/floating_ips/base.py
index 19b6a50..142eaec 100644
--- a/tempest/api/compute/floating_ips/base.py
+++ b/tempest/api/compute/floating_ips/base.py
@@ -19,8 +19,8 @@
class BaseFloatingIPsTest(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
# Floating IP actions might need a full network configuration
cls.set_network_resources(network=True, subnet=True,
router=True, dhcp=True)
- super(BaseFloatingIPsTest, cls).resource_setup()
+ super(BaseFloatingIPsTest, cls).setup_credentials()
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index e6f4fb0..f65223e 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -17,7 +17,6 @@
from tempest.api.compute.floating_ips import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -26,16 +25,20 @@
floating_ip = None
@classmethod
+ def setup_clients(cls):
+ super(FloatingIPsTestJSON, cls).setup_clients()
+ cls.client = cls.floating_ips_client
+
+ @classmethod
def resource_setup(cls):
super(FloatingIPsTestJSON, cls).resource_setup()
- cls.client = cls.floating_ips_client
cls.floating_ip_id = None
# Server creation
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
# Floating IP creation
- resp, body = cls.client.create_floating_ip()
+ body = cls.client.create_floating_ip()
cls.floating_ip_id = body['id']
cls.floating_ip = body['ip']
@@ -43,7 +46,7 @@
def resource_cleanup(cls):
# Deleting the floating IP which is created in this method
if cls.floating_ip_id:
- resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
+ cls.client.delete_floating_ip(cls.floating_ip_id)
super(FloatingIPsTestJSON, cls).resource_cleanup()
def _try_delete_floating_ip(self, floating_ip_id):
@@ -51,93 +54,89 @@
try:
self.client.delete_floating_ip(floating_ip_id)
# if not found, it depicts it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@test.attr(type='gate')
+ @test.idempotent_id('f7bfb946-297e-41b8-9e8c-aba8e9bb5194')
@test.services('network')
def test_allocate_floating_ip(self):
# Positive test:Allocation of a new floating IP to a project
# should be successful
- resp, body = self.client.create_floating_ip()
+ body = self.client.create_floating_ip()
floating_ip_id_allocated = body['id']
self.addCleanup(self.client.delete_floating_ip,
floating_ip_id_allocated)
- self.assertEqual(200, resp.status)
- resp, floating_ip_details = \
+ floating_ip_details = \
self.client.get_floating_ip_details(floating_ip_id_allocated)
# Checking if the details of allocated IP is in list of floating IP
- resp, body = self.client.list_floating_ips()
+ body = self.client.list_floating_ips()
self.assertIn(floating_ip_details, body)
@test.attr(type='gate')
+ @test.idempotent_id('de45e989-b5ca-4a9b-916b-04a52e7bbb8b')
@test.services('network')
def test_delete_floating_ip(self):
# Positive test:Deletion of valid floating IP from project
# should be successful
# Creating the floating IP that is to be deleted in this method
- resp, floating_ip_body = self.client.create_floating_ip()
+ floating_ip_body = self.client.create_floating_ip()
self.addCleanup(self._try_delete_floating_ip, floating_ip_body['id'])
- # Storing the details of floating IP before deleting it
- cli_resp = self.client.get_floating_ip_details(floating_ip_body['id'])
- resp, floating_ip_details = cli_resp
# Deleting the floating IP from the project
- resp, body = self.client.delete_floating_ip(floating_ip_body['id'])
- self.assertEqual(202, resp.status)
+ self.client.delete_floating_ip(floating_ip_body['id'])
# Check it was really deleted.
self.client.wait_for_resource_deletion(floating_ip_body['id'])
@test.attr(type='gate')
+ @test.idempotent_id('307efa27-dc6f-48a0-8cd2-162ce3ef0b52')
@test.services('network')
def test_associate_disassociate_floating_ip(self):
# Positive test:Associate and disassociate the provided floating IP
# to a specific server should be successful
# Association of floating IP to fixed IP address
- resp, body = self.client.associate_floating_ip_to_server(
+ self.client.associate_floating_ip_to_server(
self.floating_ip,
self.server_id)
- self.assertEqual(202, resp.status)
# Check instance_id in the floating_ip body
- resp, body = self.client.get_floating_ip_details(self.floating_ip_id)
+ body = self.client.get_floating_ip_details(self.floating_ip_id)
self.assertEqual(self.server_id, body['instance_id'])
# Disassociation of floating IP that was associated in this method
- resp, body = self.client.disassociate_floating_ip_from_server(
+ self.client.disassociate_floating_ip_from_server(
self.floating_ip,
self.server_id)
- self.assertEqual(202, resp.status)
@test.attr(type='gate')
+ @test.idempotent_id('6edef4b2-aaf1-4abc-bbe3-993e2561e0fe')
@test.services('network')
def test_associate_already_associated_floating_ip(self):
# positive test:Association of an already associated floating IP
# to specific server should change the association of the Floating IP
# Create server so as to use for Multiple association
new_name = data_utils.rand_name('floating_server')
- resp, body = self.create_test_server(name=new_name)
+ body = self.create_test_server(name=new_name)
self.servers_client.wait_for_server_status(body['id'], 'ACTIVE')
self.new_server_id = body['id']
+ self.addCleanup(self.servers_client.delete_server, self.new_server_id)
# Associating floating IP for the first time
- resp, _ = self.client.associate_floating_ip_to_server(
+ self.client.associate_floating_ip_to_server(
self.floating_ip,
self.server_id)
# Associating floating IP for the second time
- resp, body = self.client.associate_floating_ip_to_server(
+ self.client.associate_floating_ip_to_server(
self.floating_ip,
self.new_server_id)
- self.addCleanup(self.servers_client.delete_server, self.new_server_id)
- if (resp['status'] is not None):
- self.addCleanup(self.client.disassociate_floating_ip_from_server,
- self.floating_ip,
- self.new_server_id)
+ self.addCleanup(self.client.disassociate_floating_ip_from_server,
+ self.floating_ip,
+ self.new_server_id)
# Make sure no longer associated with old server
- self.assertRaises((exceptions.NotFound,
+ self.assertRaises((lib_exc.NotFound,
lib_exc.UnprocessableEntity,
- exceptions.Conflict),
+ lib_exc.Conflict),
self.client.disassociate_floating_ip_from_server,
self.floating_ip, self.server_id)
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index b08df97..2c08ae7 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -15,10 +15,11 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute.floating_ips import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -28,16 +29,20 @@
server_id = None
@classmethod
- def resource_setup(cls):
- super(FloatingIPsNegativeTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(FloatingIPsNegativeTestJSON, cls).setup_clients()
cls.client = cls.floating_ips_client
+ @classmethod
+ def resource_setup(cls):
+ super(FloatingIPsNegativeTestJSON, cls).resource_setup()
+
# Server creation
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
# Generating a nonexistent floatingIP id
cls.floating_ip_ids = []
- resp, body = cls.client.list_floating_ips()
+ body = cls.client.list_floating_ips()
for i in range(len(body)):
cls.floating_ip_ids.append(body[i]['id'])
while True:
@@ -48,48 +53,53 @@
break
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
@test.services('network')
def test_allocate_floating_ip_from_nonexistent_pool(self):
# Negative test:Allocation of a new floating IP from a nonexistent_pool
# to a project should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.create_floating_ip,
"non_exist_pool")
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
@test.services('network')
def test_delete_nonexistent_floating_ip(self):
# Negative test:Deletion of a nonexistent floating IP
# from project should fail
# Deleting the non existent floating IP
- self.assertRaises(exceptions.NotFound, self.client.delete_floating_ip,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_floating_ip,
self.non_exist_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
@test.services('network')
def test_associate_nonexistent_floating_ip(self):
# Negative test:Association of a non existent floating IP
# to specific server should fail
# Associating non existent floating IP
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.associate_floating_ip_to_server,
"0.0.0.0", self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
@test.services('network')
def test_dissociate_nonexistent_floating_ip(self):
# Negative test:Dissociation of a non existent floating IP should fail
# Dissociating non existent floating IP
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.disassociate_floating_ip_from_server,
"0.0.0.0", self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
@test.services('network')
def test_associate_ip_to_server_without_passing_floating_ip(self):
# Negative test:Association of empty floating IP to specific server
# should raise NotFound or BadRequest(In case of Nova V2.1) exception.
- self.assertRaises((exceptions.NotFound, exceptions.BadRequest),
+ self.assertRaises((lib_exc.NotFound, lib_exc.BadRequest),
self.client.associate_floating_ip_to_server,
'', self.server_id)
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 7af9ca7..c18ecb7 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -20,13 +20,17 @@
class FloatingIPDetailsTestJSON(base.BaseV2ComputeTest):
@classmethod
+ def setup_clients(cls):
+ super(FloatingIPDetailsTestJSON, cls).setup_clients()
+ cls.client = cls.floating_ips_client
+
+ @classmethod
def resource_setup(cls):
super(FloatingIPDetailsTestJSON, cls).resource_setup()
- cls.client = cls.floating_ips_client
cls.floating_ip = []
cls.floating_ip_id = []
for i in range(3):
- resp, body = cls.client.create_floating_ip()
+ body = cls.client.create_floating_ip()
cls.floating_ip.append(body)
cls.floating_ip_id.append(body['id'])
@@ -37,11 +41,11 @@
super(FloatingIPDetailsTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('16db31c3-fb85-40c9-bbe2-8cf7b67ff99f')
@test.services('network')
def test_list_floating_ips(self):
# Positive test:Should return the list of floating IPs
- resp, body = self.client.list_floating_ips()
- self.assertEqual(200, resp.status)
+ body = self.client.list_floating_ips()
floating_ips = body
self.assertNotEqual(0, len(floating_ips),
"Expected floating IPs. Got zero.")
@@ -49,20 +53,19 @@
self.assertIn(self.floating_ip[i], floating_ips)
@test.attr(type='gate')
+ @test.idempotent_id('eef497e0-8ff7-43c8-85ef-558440574f84')
@test.services('network')
def test_get_floating_ip_details(self):
# Positive test:Should be able to GET the details of floatingIP
# Creating a floating IP for which details are to be checked
- resp, body = self.client.create_floating_ip()
+ body = self.client.create_floating_ip()
floating_ip_id = body['id']
self.addCleanup(self.client.delete_floating_ip,
floating_ip_id)
floating_ip_instance_id = body['instance_id']
floating_ip_ip = body['ip']
floating_ip_fixed_ip = body['fixed_ip']
- resp, body = \
- self.client.get_floating_ip_details(floating_ip_id)
- self.assertEqual(200, resp.status)
+ body = self.client.get_floating_ip_details(floating_ip_id)
# Comparing the details of floating IP
self.assertEqual(floating_ip_instance_id,
body['instance_id'])
@@ -72,10 +75,10 @@
self.assertEqual(floating_ip_id, body['id'])
@test.attr(type='gate')
+ @test.idempotent_id('df389fc8-56f5-43cc-b290-20eda39854d3')
@test.services('network')
def test_list_floating_ip_pools(self):
# Positive test:Should return the list of floating IP Pools
- resp, floating_ip_pools = self.client.list_floating_ip_pools()
- self.assertEqual(200, resp.status)
+ floating_ip_pools = self.client.list_floating_ip_pools()
self.assertNotEqual(0, len(floating_ip_pools),
"Expected floating IP Pools. Got zero.")
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index c343018..13d0719 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -15,10 +15,11 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -27,11 +28,12 @@
class FloatingIPDetailsNegativeTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
- super(FloatingIPDetailsNegativeTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(FloatingIPDetailsNegativeTestJSON, cls).setup_clients()
cls.client = cls.floating_ips_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
@test.services('network')
def test_get_nonexistent_floating_ip_details(self):
# Negative test:Should not be able to GET the details
@@ -41,5 +43,5 @@
non_exist_id = str(uuid.uuid4())
else:
non_exist_id = data_utils.rand_int_id(start=999)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_floating_ip_details, non_exist_id)
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index c3b144d..8193a55 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -53,6 +53,7 @@
self.client.set_image_metadata(self.image_id, meta)
@test.attr(type='gate')
+ @test.idempotent_id('37ec6edd-cf30-4c53-bd45-ae74db6b0531')
def test_list_image_metadata(self):
# All metadata key/value pairs for an image should be returned
resp_metadata = self.client.list_image_metadata(self.image_id)
@@ -60,6 +61,7 @@
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('ece7befc-d3ce-42a4-b4be-c3067a418c29')
def test_set_image_metadata(self):
# The metadata for the image should match the new values
req_metadata = {'os_version': 'value2', 'architecture': 'value3'}
@@ -70,6 +72,7 @@
self.assertEqual(req_metadata, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('7b491c11-a9d5-40fe-a696-7f7e03d3fea2')
def test_update_image_metadata(self):
# The metadata for the image should match the updated values
req_metadata = {'os_version': 'alt1', 'architecture': 'value3'}
@@ -83,6 +86,7 @@
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('4f5db52f-6685-4c75-b848-f4bb363f9aa6')
def test_get_image_metadata_item(self):
# The value for a specific metadata key should be returned
meta = self.client.get_image_metadata_item(self.image_id,
@@ -90,6 +94,7 @@
self.assertEqual('value2', meta['os_distro'])
@test.attr(type='gate')
+ @test.idempotent_id('f2de776a-4778-4d90-a5da-aae63aee64ae')
def test_set_image_metadata_item(self):
# The value provided for the given meta item should be set for
# the image
@@ -101,6 +106,7 @@
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('a013796c-ba37-4bb5-8602-d944511def14')
def test_delete_image_metadata_item(self):
# The metadata value/key pair should be deleted from the image
self.client.delete_image_metadata_item(self.image_id,
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 73412ff..d181ed9 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -27,48 +28,54 @@
cls.client = cls.images_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
def test_list_nonexistent_image_metadata(self):
# Negative test: List on nonexistent image
# metadata should not happen
- self.assertRaises(exceptions.NotFound, self.client.list_image_metadata,
+ self.assertRaises(lib_exc.NotFound, self.client.list_image_metadata,
data_utils.rand_uuid())
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a403ef9e-9f95-427c-b70a-3ce3388796f1')
def test_update_nonexistent_image_metadata(self):
# Negative test:An update should not happen for a non-existent image
meta = {'os_distro': 'alt1', 'os_version': 'alt2'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_image_metadata,
data_utils.rand_uuid(), meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('41ae052c-6ee6-405c-985e-5712393a620d')
def test_get_nonexistent_image_metadata_item(self):
# Negative test: Get on non-existent image should not happen
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_image_metadata_item,
data_utils.rand_uuid(), 'os_version')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('dc64f2ce-77e8-45b0-88c8-e15041d08eaf')
def test_set_nonexistent_image_metadata(self):
# Negative test: Metadata should not be set to a non-existent image
meta = {'os_distro': 'alt1', 'os_version': 'alt2'}
- self.assertRaises(exceptions.NotFound, self.client.set_image_metadata,
+ self.assertRaises(lib_exc.NotFound, self.client.set_image_metadata,
data_utils.rand_uuid(), meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('2154fd03-ab54-457c-8874-e6e3eb56e9cf')
def test_set_nonexistent_image_metadata_item(self):
# Negative test: Metadata item should not be set to a
# nonexistent image
meta = {'os_distro': 'alt'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.set_image_metadata_item,
data_utils.rand_uuid(), 'os_distro',
meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('848e157f-6bcf-4b2e-a5dd-5124025a8518')
def test_delete_nonexistent_image_metadata_item(self):
# Negative test: Shouldn't be able to delete metadata
# item from non-existent image
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_image_metadata_item,
data_utils.rand_uuid(), 'os_distro')
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index dc27a70..396d629 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -38,9 +38,10 @@
cls.servers_client = cls.servers_client
@test.attr(type='gate')
+ @test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
def test_delete_saving_image(self):
snapshot_name = data_utils.rand_name('test-snap-')
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
self.addCleanup(self.servers_client.delete_server, server['id'])
image = self.create_image_from_server(server['id'],
name=snapshot_name,
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 58fc20d..ee52f37 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -12,10 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -39,9 +40,10 @@
cls.servers_client = cls.servers_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
def test_create_image_from_deleted_server(self):
# An image should not be created if the server instance is removed
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
# Delete server before trying to create server
self.servers_client.delete_server(server['id'])
@@ -49,11 +51,12 @@
# Create a new image after server is deleted
name = data_utils.rand_name('image')
meta = {'image_type': 'test'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.create_image_from_server,
server['id'], name=name, meta=meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('82c5b0c4-9dbd-463c-872b-20c4755aae7f')
def test_create_image_from_invalid_server(self):
# An image should not be created with invalid server id
# Create a new image with invalid server id
@@ -61,12 +64,13 @@
meta = {'image_type': 'test'}
resp = {}
resp['status'] = None
- self.assertRaises(exceptions.NotFound, self.create_image_from_server,
+ self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
'!@#$%^&*()', name=name, meta=meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('aaacd1d0-55a2-4ce8-818a-b5439df8adc9')
def test_create_image_from_stopped_server(self):
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
self.servers_client.stop(server['id'])
self.servers_client.wait_for_server_status(server['id'],
'SHUTOFF')
@@ -80,54 +84,62 @@
self.assertEqual(snapshot_name, image['name'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
def test_create_image_specify_uuid_35_characters_or_less(self):
# Return an error if Image ID passed is 35 characters or less
snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 35)
- self.assertRaises(exceptions.NotFound, self.client.create_image,
+ self.assertRaises(lib_exc.NotFound, self.client.create_image,
test_uuid, snapshot_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('36741560-510e-4cc2-8641-55fe4dfb2437')
def test_create_image_specify_uuid_37_characters_or_more(self):
# Return an error if Image ID passed is 37 characters or more
snapshot_name = data_utils.rand_name('test-snap-')
test_uuid = ('a' * 37)
- self.assertRaises(exceptions.NotFound, self.client.create_image,
+ self.assertRaises(lib_exc.NotFound, self.client.create_image,
test_uuid, snapshot_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('381acb65-785a-4942-94ce-d8f8c84f1f0f')
def test_delete_image_with_invalid_image_id(self):
# An image should not be deleted with invalid image id
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
'!@$%^&*()')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('137aef61-39f7-44a1-8ddf-0adf82511701')
def test_delete_non_existent_image(self):
# Return an error while trying to delete a non-existent image
non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
non_existent_image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e6e41425-af5c-4fe6-a4b5-7b7b963ffda5')
def test_delete_image_blank_id(self):
# Return an error while trying to delete an image with blank Id
- self.assertRaises(exceptions.NotFound, self.client.delete_image, '')
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('924540c3-f1f1-444c-8f58-718958b6724e')
def test_delete_image_non_hex_string_id(self):
# Return an error while trying to delete an image with non hex id
image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('68e2c175-bd26-4407-ac0f-4ea9ce2139ea')
def test_delete_image_negative_image_id(self):
# Return an error while trying to delete an image with negative id
- self.assertRaises(exceptions.NotFound, self.client.delete_image, -1)
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image, -1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b340030d-82cd-4066-a314-c72fb7c59277')
def test_delete_image_id_is_over_35_character_limit(self):
# Return an error while trying to delete image with id over limit
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
'11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 79cd27a..abdeb18 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -59,7 +59,7 @@
% cls.__name__)
raise cls.skipException(skip_msg)
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
def _get_default_flavor_disk_size(self, flavor_id):
@@ -67,6 +67,7 @@
return flavor['disk']
@test.attr(type='smoke')
+ @test.idempotent_id('3731d080-d4c5-4872-b41a-64d0d0021314')
def test_create_delete_image(self):
# Create a new image
@@ -96,6 +97,7 @@
self.client.wait_for_resource_deletion(image_id)
@test.attr(type=['gate'])
+ @test.idempotent_id('3b7c6fe4-dfe7-477c-9243-b06359db51e6')
def test_create_image_specify_multibyte_character_image_name(self):
# prefix character is:
# http://www.fileformat.info/info/unicode/char/1F4A9/index.htm
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 46cec9b..f6a4aec 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -14,10 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest import test
@@ -67,28 +68,31 @@
% cls.__name__)
raise cls.skipException(skip_msg)
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
cls.image_ids = []
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('55d1d38c-dd66-4933-9c8e-7d92aeb60ddc')
def test_create_image_specify_invalid_metadata(self):
# Return an error when creating image with invalid metadata
snapshot_name = data_utils.rand_name('test-snap-')
meta = {'': ''}
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
self.server_id, snapshot_name, meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3d24d11f-5366-4536-bd28-cff32b748eca')
def test_create_image_specify_metadata_over_limits(self):
# Return an error when creating image with meta data over 256 chars
snapshot_name = data_utils.rand_name('test-snap-')
meta = {'a' * 260: 'b' * 260}
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
self.server_id, snapshot_name, meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0460efcf-ee88-4f94-acef-1bf658695456')
def test_create_second_image_when_first_image_is_being_saved(self):
# Disallow creating another image when first image is being saved
@@ -102,18 +106,20 @@
# Create second snapshot
alt_snapshot_name = data_utils.rand_name('test-snap-')
- self.assertRaises(exceptions.Conflict, self.client.create_image,
+ self.assertRaises(lib_exc.Conflict, self.client.create_image,
self.server_id, alt_snapshot_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
def test_create_image_specify_name_over_256_chars(self):
# Return an error if snapshot name over 256 characters is passed
snapshot_name = data_utils.rand_name('a' * 260)
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
self.server_id, snapshot_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0894954d-2db2-4195-a45b-ffec0bc0187e')
def test_delete_image_that_is_not_yet_active(self):
# Return an error while trying to delete an image what is creating
@@ -127,4 +133,4 @@
self.client.delete_image(image_id)
self.image_ids.remove(image_id)
- self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+ self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index 742c2dd..6176d85 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -69,8 +69,8 @@
return
# Create instances and snapshots via nova
- resp, cls.server1 = cls.create_test_server()
- resp, cls.server2 = cls.create_test_server(wait_until='ACTIVE')
+ cls.server1 = cls.create_test_server()
+ cls.server2 = cls.create_test_server(wait_until='ACTIVE')
# NOTE(sdague) this is faster than doing the sync wait_util on both
cls.servers_client.wait_for_server_status(cls.server1['id'],
'ACTIVE')
@@ -93,6 +93,7 @@
cls.snapshot2_id = cls.snapshot2['id']
@test.attr(type='gate')
+ @test.idempotent_id('a3f5b513-aeb3-42a9-b18e-f091ef73254d')
def test_list_images_filter_by_status(self):
# The list of images should contain only images with the
# provided status
@@ -104,6 +105,7 @@
self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
@test.attr(type='gate')
+ @test.idempotent_id('33163b73-79f5-4d07-a7ea-9213bcc468ff')
def test_list_images_filter_by_name(self):
# List of all images should contain the expected images filtered
# by name
@@ -114,6 +116,7 @@
self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
+ @test.idempotent_id('9f238683-c763-45aa-b848-232ec3ce3105')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.attr(type='gate')
@@ -131,6 +134,7 @@
self.assertFalse(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @test.idempotent_id('05a377b8-28cf-4734-a1e6-2ab5c38bf606')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.attr(type='gate')
@@ -150,6 +154,7 @@
self.assertTrue(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @test.idempotent_id('e3356918-4d3e-4756-81d5-abc4524ba29f')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.attr(type='gate')
@@ -168,15 +173,15 @@
if i['id'] == self.image_ref]))
@test.attr(type='gate')
+ @test.idempotent_id('3a484ca9-67ba-451e-b494-7fcf28d32d62')
def test_list_images_limit_results(self):
# Verify only the expected number of results are returned
params = {'limit': '1'}
images = self.client.list_images(params)
- # when _interface='xml', one element for images_links in images
- # ref: Question #224349
self.assertEqual(1, len([x for x in images if 'id' in x]))
@test.attr(type='gate')
+ @test.idempotent_id('18bac3ae-da27-436c-92a9-b22474d13aab')
def test_list_images_filter_by_changes_since(self):
# Verify only updated images are returned in the detailed list
@@ -188,6 +193,7 @@
self.assertTrue(found)
@test.attr(type='gate')
+ @test.idempotent_id('9b0ea018-6185-4f71-948a-a123a107988e')
def test_list_images_with_detail_filter_by_status(self):
# Detailed list of all images should only contain images
# with the provided status
@@ -199,6 +205,7 @@
self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
@test.attr(type='gate')
+ @test.idempotent_id('644ea267-9bd9-4f3b-af9f-dffa02396a17')
def test_list_images_with_detail_filter_by_name(self):
# Detailed list of all images should contain the expected
# images filtered by name
@@ -210,6 +217,7 @@
self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
@test.attr(type='gate')
+ @test.idempotent_id('ba2fa9a9-b672-47cc-b354-3b4c0600e2cb')
def test_list_images_with_detail_limit_results(self):
# Verify only the expected number of results (with full details)
# are returned
@@ -217,6 +225,7 @@
images = self.client.list_images_with_detail(params)
self.assertEqual(1, len(images))
+ @test.idempotent_id('8c78f822-203b-4bf6-8bba-56ebd551cf84')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.attr(type='gate')
@@ -236,6 +245,7 @@
self.assertTrue(any([i for i in images
if i['id'] == self.snapshot3_id]))
+ @test.idempotent_id('888c0cc0-7223-43c5-9db0-b125fd0a393b')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.attr(type='gate')
@@ -255,6 +265,7 @@
if i['id'] == self.image_ref]))
@test.attr(type='gate')
+ @test.idempotent_id('7d439e18-ac2e-4827-b049-7e18004712c4')
def test_list_images_with_detail_filter_by_changes_since(self):
# Verify an update image is returned
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index a8f2ae7..e5418ad 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -12,10 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -32,8 +33,9 @@
cls.client = cls.images_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
def test_get_nonexistent_image(self):
# Check raises a NotFound
nonexistent_image = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.get_image,
+ self.assertRaises(lib_exc.NotFound, self.client.get_image,
nonexistent_image)
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index cd01147..36451ec 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -31,12 +31,14 @@
cls.client = cls.images_client
@test.attr(type='smoke')
+ @test.idempotent_id('490d0898-e12a-463f-aef0-c50156b9f789')
def test_get_image(self):
# Returns the correct details for a single image
image = self.client.get_image(self.image_ref)
self.assertEqual(self.image_ref, image['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('fd51b7f4-d4a3-4331-9885-866658112a6f')
def test_list_images(self):
# The list of all images should contain the image
images = self.client.list_images()
@@ -44,6 +46,7 @@
self.assertTrue(found)
@test.attr(type='smoke')
+ @test.idempotent_id('9f94cb6b-7f10-48c5-b911-a0b84d7d4cd6')
def test_list_images_with_detail(self):
# Detailed list of all images should contain the expected images
images = self.client.list_images_with_detail()
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index d7884ab..972f0de 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -36,6 +36,7 @@
return body
@test.attr(type='gate')
+ @test.idempotent_id('1d1dbedb-d7a0-432a-9d09-83f543c3c19b')
def test_keypairs_create_list_delete(self):
# Keypairs created should be available in the response list
# Create 3 keypairs
@@ -64,6 +65,7 @@
% ', '.join(m_key['name'] for m_key in missing_kps))
@test.attr(type='gate')
+ @test.idempotent_id('6c1d3123-4519-4742-9194-622cb1714b7d')
def test_keypair_create_delete(self):
# Keypair should be created, verified and deleted
k_name = data_utils.rand_name('keypair-')
@@ -77,6 +79,7 @@
"Field private_key is empty or not found.")
@test.attr(type='gate')
+ @test.idempotent_id('a4233d5d-52d8-47cc-9a25-e1864527e3df')
def test_get_keypair_detail(self):
# Keypair should be created, Got details by name and deleted
k_name = data_utils.rand_name('keypair-')
@@ -92,6 +95,7 @@
"Field public_key is empty or not found.")
@test.attr(type='gate')
+ @test.idempotent_id('39c90c6a-304a-49dd-95ec-2366129def05')
def test_keypair_create_with_pub_key(self):
# Keypair should be created with a given public key
k_name = data_utils.rand_name('keypair-')
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 4e06d6c..e63f3c7 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -14,9 +14,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -32,62 +33,70 @@
self.addCleanup(self.client.delete_keypair, keypair_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('29cca892-46ae-4d48-bc32-8fe7e731eb81')
def test_keypair_create_with_invalid_pub_key(self):
# Keypair should not be created with a non RSA public key
k_name = data_utils.rand_name('keypair-')
pub_key = "ssh-rsa JUNK nova@ubuntu"
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self._create_keypair, k_name, pub_key)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7cc32e47-4c42-489d-9623-c5e2cb5a2fa5')
def test_keypair_delete_nonexistent_key(self):
# Non-existent key deletion should throw a proper error
k_name = data_utils.rand_name("keypair-non-existent-")
- self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_keypair,
k_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('dade320e-69ca-42a9-ba4a-345300f127e0')
def test_create_keypair_with_empty_public_key(self):
# Keypair should not be created with an empty public key
k_name = data_utils.rand_name("keypair-")
pub_key = ' '
- self.assertRaises(exceptions.BadRequest, self._create_keypair,
+ self.assertRaises(lib_exc.BadRequest, self._create_keypair,
k_name, pub_key)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fc100c19-2926-4b9c-8fdc-d0589ee2f9ff')
def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
# Keypair should not be created when public key bits are too long
k_name = data_utils.rand_name("keypair-")
pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
- self.assertRaises(exceptions.BadRequest, self._create_keypair,
+ self.assertRaises(lib_exc.BadRequest, self._create_keypair,
k_name, pub_key)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0359a7f1-f002-4682-8073-0c91e4011b7c')
def test_create_keypair_with_duplicate_name(self):
# Keypairs with duplicate names should not be created
k_name = data_utils.rand_name('keypair-')
self.client.create_keypair(k_name)
# Now try the same keyname to create another key
- self.assertRaises(exceptions.Conflict, self._create_keypair,
+ self.assertRaises(lib_exc.Conflict, self._create_keypair,
k_name)
self.client.delete_keypair(k_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1398abe1-4a84-45fb-9294-89f514daff00')
def test_create_keypair_with_empty_name_string(self):
# Keypairs with name being an empty string should not be created
- self.assertRaises(exceptions.BadRequest, self._create_keypair,
+ self.assertRaises(lib_exc.BadRequest, self._create_keypair,
'')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3faa916f-779f-4103-aca7-dc3538eee1b7')
def test_create_keypair_with_long_keynames(self):
# Keypairs with name longer than 255 chars should not be created
k_name = 'keypair-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest, self._create_keypair,
+ self.assertRaises(lib_exc.BadRequest, self._create_keypair,
k_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('45fbe5e0-acb5-49aa-837a-ff8d0719db91')
def test_create_keypair_invalid_name(self):
# Keypairs with name being an invalid name should not be created
k_name = 'key_/.\@:'
- self.assertRaises(exceptions.BadRequest, self._create_keypair,
+ self.assertRaises(lib_exc.BadRequest, self._create_keypair,
k_name)
diff --git a/tempest/api/compute/limits/test_absolute_limits.py b/tempest/api/compute/limits/test_absolute_limits.py
index 520dfa9..39ed2a1 100644
--- a/tempest/api/compute/limits/test_absolute_limits.py
+++ b/tempest/api/compute/limits/test_absolute_limits.py
@@ -20,11 +20,12 @@
class AbsoluteLimitsTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
- super(AbsoluteLimitsTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(AbsoluteLimitsTestJSON, cls).setup_clients()
cls.client = cls.limits_client
@test.attr(type='gate')
+ @test.idempotent_id('b54c66af-6ab6-4cf0-a9e5-a0cb58d75e0b')
def test_absLimits_get(self):
# To check if all limits are present in the response
absolute_limits = self.client.get_absolute_limits()
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index d537d83..507f24e 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common import tempest_fixtures as fixtures
-from tempest import exceptions
from tempest import test
@@ -27,12 +28,13 @@
super(AbsoluteLimitsNegativeTestJSON, self).setUp()
@classmethod
- def resource_setup(cls):
- super(AbsoluteLimitsNegativeTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(AbsoluteLimitsNegativeTestJSON, cls).setup_clients()
cls.client = cls.limits_client
cls.server_client = cls.servers_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('215cd465-d8ae-49c9-bf33-9c911913a5c8')
def test_max_image_meta_exceed_limit(self):
# We should not create vm with image meta over maxImageMeta limit
# Get max limit value
@@ -51,5 +53,5 @@
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.create_test_server, meta=meta_data)
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index 05cad9a..f70f6d3 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -19,7 +19,7 @@
class BaseSecurityGroupsTest(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
# A network and a subnet will be created for these tests
cls.set_network_resources(network=True, subnet=True)
- super(BaseSecurityGroupsTest, cls).resource_setup()
+ super(BaseSecurityGroupsTest, cls).setup_credentials()
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 527f2dd..70394d8 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -23,9 +23,13 @@
class SecurityGroupRulesTestJSON(base.BaseSecurityGroupsTest):
@classmethod
+ def setup_clients(cls):
+ super(SecurityGroupRulesTestJSON, cls).setup_clients()
+ cls.client = cls.security_groups_client
+
+ @classmethod
def resource_setup(cls):
super(SecurityGroupRulesTestJSON, cls).resource_setup()
- cls.client = cls.security_groups_client
cls.neutron_available = CONF.service_available.neutron
cls.ip_protocol = 'tcp'
cls.from_port = 22
@@ -56,6 +60,7 @@
"Miss-matched key is %s" % key)
@test.attr(type='smoke')
+ @test.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
@test.services('network')
def test_security_group_rules_create(self):
# Positive test: Creation of Security Group rule
@@ -74,6 +79,7 @@
self._check_expected_response(rule)
@test.attr(type='smoke')
+ @test.idempotent_id('7a01873e-3c38-4f30-80be-31a043cfe2fd')
@test.services('network')
def test_security_group_rules_create_with_optional_cidr(self):
# Positive test: Creation of Security Group rule
@@ -97,6 +103,7 @@
self._check_expected_response(rule)
@test.attr(type='smoke')
+ @test.idempotent_id('7f5d2899-7705-4d4b-8458-4505188ffab6')
@test.services('network')
def test_security_group_rules_create_with_optional_group_id(self):
# Positive test: Creation of Security Group rule
@@ -125,6 +132,7 @@
self._check_expected_response(rule)
@test.attr(type='smoke')
+ @test.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
@test.services('network')
def test_security_group_rules_list(self):
# Positive test: Created Security Group rules should be
@@ -160,6 +168,7 @@
self.assertTrue(any([i for i in rules if i['id'] == rule2_id]))
@test.attr(type='smoke')
+ @test.idempotent_id('fc5c5acf-2091-43a6-a6ae-e42760e9ffaf')
@test.services('network')
def test_security_group_rules_delete_when_peer_group_deleted(self):
# Positive test:rule will delete when peer group deleting
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index d97c404..f6a50ee 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -13,10 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute.security_groups import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -32,11 +33,12 @@
class SecurityGroupRulesNegativeTestJSON(base.BaseSecurityGroupsTest):
@classmethod
- def resource_setup(cls):
- super(SecurityGroupRulesNegativeTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(SecurityGroupRulesNegativeTestJSON, cls).setup_clients()
cls.client = cls.security_groups_client
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
@test.services('network')
def test_create_security_group_rule_with_non_existent_id(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -46,11 +48,12 @@
ip_protocol = 'tcp'
from_port = 22
to_port = 22
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
@test.services('network')
def test_create_security_group_rule_with_invalid_id(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -60,11 +63,12 @@
ip_protocol = 'tcp'
from_port = 22
to_port = 22
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
@test.services('network')
def test_create_security_group_rule_duplicate(self):
# Negative test: Create Security Group rule duplicate should fail
@@ -83,11 +87,12 @@
to_port)
self.addCleanup(self.client.delete_security_group_rule, rule['id'])
# Add the same rule to the group should fail
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
@test.services('network')
def test_create_security_group_rule_with_invalid_ip_protocol(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -100,11 +105,12 @@
from_port = 22
to_port = 22
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
@test.services('network')
def test_create_security_group_rule_with_invalid_from_port(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -116,11 +122,12 @@
ip_protocol = 'tcp'
from_port = data_utils.rand_int_id(start=65536)
to_port = 22
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
@test.services('network')
def test_create_security_group_rule_with_invalid_to_port(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -132,11 +139,12 @@
ip_protocol = 'tcp'
from_port = 22
to_port = data_utils.rand_int_id(start=65536)
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
@test.services('network')
def test_create_security_group_rule_with_invalid_port_range(self):
# Negative test: Creation of Security Group rule should FAIL
@@ -148,16 +156,17 @@
ip_protocol = 'tcp'
from_port = 22
to_port = 21
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group_rule,
secgroup_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
@test.services('network')
def test_delete_security_group_rule_with_non_existent_id(self):
# Negative test: Deletion of Security Group rule should be FAIL
# with non existent id
non_existent_rule_id = not_existing_id()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_security_group_rule,
non_existent_rule_id)
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 909d444..5a11854 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -13,20 +13,22 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute.security_groups import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class SecurityGroupsTestJSON(base.BaseSecurityGroupsTest):
@classmethod
- def resource_setup(cls):
- super(SecurityGroupsTestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(SecurityGroupsTestJSON, cls).setup_clients()
cls.client = cls.security_groups_client
@test.attr(type='smoke')
+ @test.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
@test.services('network')
def test_security_groups_create_list_delete(self):
# Positive test:Should return the list of Security Groups
@@ -59,6 +61,7 @@
for m_group in deleted_sgs))
@test.attr(type='smoke')
+ @test.idempotent_id('ecc0da4a-2117-48af-91af-993cca39a615')
@test.services('network')
def test_security_group_create_get_delete(self):
# Security Group should be created, fetched and deleted
@@ -81,6 +84,7 @@
self.client.wait_for_resource_deletion(securitygroup['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('fe4abc0d-83f5-4c50-ad11-57a1127297a2')
@test.services('network')
def test_server_security_groups(self):
# Checks that security groups may be added and linked to a server
@@ -93,27 +97,25 @@
# Create server and add the security group created
# above to the server we just created
server_name = data_utils.rand_name('server')
- resp, server = self.create_test_server(name=server_name)
+ server = self.create_test_server(name=server_name)
server_id = server['id']
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
- resp, body = self.servers_client.add_security_group(server_id,
- sg['name'])
+ self.servers_client.add_security_group(server_id, sg['name'])
# Check that we are not able to delete the security
# group since it is in use by an active server
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.delete_security_group,
sg['id'])
# Reboot and add the other security group
- resp, body = self.servers_client.reboot(server_id, 'HARD')
+ self.servers_client.reboot(server_id, 'HARD')
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
- resp, body = self.servers_client.add_security_group(server_id,
- sg2['name'])
+ self.servers_client.add_security_group(server_id, sg2['name'])
# Check that we are not able to delete the other security
# group since it is in use by an active server
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.delete_security_group,
sg2['id'])
@@ -126,6 +128,7 @@
self.client.delete_security_group(sg2['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('7d4e1d3c-3209-4d6d-b020-986304ebad1f')
@test.services('network')
def test_update_security_groups(self):
# Update security group name and description
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index ee9f78b..0127dc7 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -14,12 +14,12 @@
# under the License.
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.api.compute.security_groups import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -28,9 +28,13 @@
class SecurityGroupsNegativeTestJSON(base.BaseSecurityGroupsTest):
@classmethod
+ def setup_clients(cls):
+ super(SecurityGroupsNegativeTestJSON, cls).setup_clients()
+ cls.client = cls.security_groups_client
+
+ @classmethod
def resource_setup(cls):
super(SecurityGroupsNegativeTestJSON, cls).resource_setup()
- cls.client = cls.security_groups_client
cls.neutron_available = CONF.service_available.neutron
def _generate_a_non_existent_security_group_id(self):
@@ -48,55 +52,59 @@
return non_exist_id
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
@test.services('network')
def test_security_group_get_nonexistent_group(self):
# Negative test:Should not be able to GET the details
# of non-existent Security Group
non_exist_id = self._generate_a_non_existent_security_group_id()
- self.assertRaises(exceptions.NotFound, self.client.get_security_group,
+ self.assertRaises(lib_exc.NotFound, self.client.get_security_group,
non_exist_id)
@decorators.skip_because(bug="1161411",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
@test.services('network')
def test_security_group_create_with_invalid_group_name(self):
# Negative test: Security Group should not be created with group name
# as an empty string/with white spaces/chars more than 255
s_description = data_utils.rand_name('description-')
# Create Security Group with empty string as group name
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, "", s_description)
# Create Security Group with white space in group name
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, " ",
s_description)
# Create Security Group with group name longer than 255 chars
s_name = 'securitygroup-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, s_name,
s_description)
@decorators.skip_because(bug="1161411",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
@test.services('network')
def test_security_group_create_with_invalid_group_description(self):
# Negative test:Security Group should not be created with description
# as an empty string/with white spaces/chars more than 255
s_name = data_utils.rand_name('securitygroup-')
# Create Security Group with empty string as description
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, s_name, "")
# Create Security Group with white space in description
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, s_name, " ")
# Create Security Group with group description longer than 255 chars
s_description = 'description-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, s_name,
s_description)
+ @test.idempotent_id('9fdb4abc-6b66-4b27-b89c-eb215a956168')
@testtools.skipIf(CONF.service_available.neutron,
"Neutron allows duplicate names for security groups")
@test.attr(type=['negative', 'smoke'])
@@ -108,11 +116,12 @@
s_description = data_utils.rand_name('description-')
self.create_security_group(s_name, s_description)
# Now try the Security Group with the same 'Name'
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_security_group, s_name,
s_description)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
@test.services('network')
def test_delete_the_default_security_group(self):
# Negative test:Deletion of the "default" Security Group should Fail
@@ -123,26 +132,29 @@
default_security_group_id = body[i]['id']
break
# Deleting the "default" Security Group
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.delete_security_group,
default_security_group_id)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
@test.services('network')
def test_delete_nonexistent_security_group(self):
# Negative test:Deletion of a non-existent Security Group should fail
non_exist_id = self._generate_a_non_existent_security_group_id()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_security_group, non_exist_id)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
@test.services('network')
def test_delete_security_group_without_passing_id(self):
# Negative test:Deletion of a Security Group with out passing ID
# should Fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_security_group, '')
+ @test.idempotent_id('00579617-fe04-4e1c-9d08-ca7467d2e34b')
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_id")
@test.attr(type=['negative', 'smoke'])
@@ -153,10 +165,11 @@
s_description = data_utils.rand_name('description-')
# Create a non int sg_id
sg_id_invalid = data_utils.rand_name('sg-')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_security_group, sg_id_invalid,
name=s_name, description=s_description)
+ @test.idempotent_id('cda8d8b4-59f8-4087-821d-20cf5a03b3b1')
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_name")
@test.attr(type=['negative', 'smoke'])
@@ -168,10 +181,11 @@
securitygroup_id = securitygroup['id']
# Update Security Group with group name longer than 255 chars
s_new_name = 'securitygroup-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_security_group,
securitygroup_id, name=s_new_name)
+ @test.idempotent_id('97d12b1c-a610-4194-93f1-ba859e718b45')
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_description")
@test.attr(type=['negative', 'smoke'])
@@ -183,18 +197,19 @@
securitygroup_id = securitygroup['id']
# Update Security Group with group description longer than 255 chars
s_new_des = 'des-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_security_group,
securitygroup_id, description=s_new_des)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
@test.services('network')
def test_update_non_existent_security_group(self):
# Update a non-existent Security Group should Fail
non_exist_id = self._generate_a_non_existent_security_group_id()
s_name = data_utils.rand_name('sg-')
s_description = data_utils.rand_name('description-')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_security_group,
non_exist_id, name=s_name,
description=s_description)
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 4b14dc4..0702f3f 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -26,14 +26,22 @@
class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(AttachInterfacesTestJSON, cls).skip_checks()
if not CONF.service_available.neutron:
raise cls.skipException("Neutron is required")
if not CONF.compute_feature_enabled.interface_attach:
raise cls.skipException("Interface attachment is not available.")
+
+ @classmethod
+ def setup_credentials(cls):
# This test class requires network and subnet
cls.set_network_resources(network=True, subnet=True)
- super(AttachInterfacesTestJSON, cls).resource_setup()
+ super(AttachInterfacesTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(AttachInterfacesTestJSON, cls).setup_clients()
cls.client = cls.os.interfaces_client
def _check_interface(self, iface, port_id=None, network_id=None,
@@ -49,37 +57,33 @@
self.assertEqual(iface['mac_addr'], mac_addr)
def _create_server_get_interfaces(self):
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, ifs = self.client.list_interfaces(server['id'])
- self.assertEqual(200, resp.status)
- resp, body = self.client.wait_for_interface_status(
+ server = self.create_test_server(wait_until='ACTIVE')
+ ifs = self.client.list_interfaces(server['id'])
+ body = self.client.wait_for_interface_status(
server['id'], ifs[0]['port_id'], 'ACTIVE')
ifs[0]['port_state'] = body['port_state']
return server, ifs
def _test_create_interface(self, server):
- resp, iface = self.client.create_interface(server['id'])
- self.assertEqual(200, resp.status)
- resp, iface = self.client.wait_for_interface_status(
+ iface = self.client.create_interface(server['id'])
+ iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface)
return iface
def _test_create_interface_by_network_id(self, server, ifs):
network_id = ifs[0]['net_id']
- resp, iface = self.client.create_interface(server['id'],
- network_id=network_id)
- self.assertEqual(200, resp.status)
- resp, iface = self.client.wait_for_interface_status(
+ iface = self.client.create_interface(server['id'],
+ network_id=network_id)
+ iface = self.client.wait_for_interface_status(
server['id'], iface['port_id'], 'ACTIVE')
self._check_interface(iface, network_id=network_id)
return iface
def _test_show_interface(self, server, ifs):
iface = ifs[0]
- resp, _iface = self.client.show_interface(server['id'],
- iface['port_id'])
- self.assertEqual(200, resp.status)
+ _iface = self.client.show_interface(server['id'],
+ iface['port_id'])
self._check_interface(iface, port_id=_iface['port_id'],
network_id=_iface['net_id'],
fixed_ip=_iface['fixed_ips'][0]['ip_address'],
@@ -88,14 +92,13 @@
def _test_delete_interface(self, server, ifs):
# NOTE(danms): delete not the first or last, but one in the middle
iface = ifs[1]
- resp, _ = self.client.delete_interface(server['id'], iface['port_id'])
- self.assertEqual(202, resp.status)
- _ifs = self.client.list_interfaces(server['id'])[1]
+ self.client.delete_interface(server['id'], iface['port_id'])
+ _ifs = self.client.list_interfaces(server['id'])
start = int(time.time())
while len(ifs) == len(_ifs):
time.sleep(self.build_interval)
- _ifs = self.client.list_interfaces(server['id'])[1]
+ _ifs = self.client.list_interfaces(server['id'])
timed_out = int(time.time()) - start >= self.build_timeout
if len(ifs) == len(_ifs) and timed_out:
message = ('Failed to delete interface within '
@@ -114,6 +117,7 @@
self.assertEqual(sorted(list1), sorted(list2))
@test.attr(type='smoke')
+ @test.idempotent_id('73fe8f02-590d-4bf1-b184-e9ca81065051')
@test.services('network')
def test_create_list_show_delete_interfaces(self):
server, ifs = self._create_server_get_interfaces()
@@ -127,7 +131,7 @@
iface = self._test_create_interface_by_network_id(server, ifs)
ifs.append(iface)
- resp, _ifs = self.client.list_interfaces(server['id'])
+ _ifs = self.client.list_interfaces(server['id'])
self._compare_iface_list(ifs, _ifs)
self._test_show_interface(server, ifs)
@@ -136,6 +140,7 @@
self.assertEqual(len(ifs) - 1, len(_ifs))
@test.attr(type='smoke')
+ @test.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
@test.services('network')
def test_add_remove_fixed_ip(self):
# Add and Remove the fixed IP to server.
@@ -144,11 +149,9 @@
self.assertTrue(interface_count > 0)
self._check_interface(ifs[0])
network_id = ifs[0]['net_id']
- resp, body = self.client.add_fixed_ip(server['id'],
- network_id)
- self.assertEqual(202, resp.status)
+ self.client.add_fixed_ip(server['id'], network_id)
# Remove the fixed IP from server.
- server_resp, server_detail = self.os.servers_client.get_server(
+ server_detail = self.os.servers_client.get_server(
server['id'])
# Get the Fixed IP from server.
fixed_ip = None
@@ -159,6 +162,4 @@
break
if fixed_ip is not None:
break
- resp, body = self.client.remove_fixed_ip(server['id'],
- fixed_ip)
- self.assertEqual(202, resp.status)
+ self.client.remove_fixed_ip(server['id'], fixed_ip)
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 5ddf053..5962042 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -29,8 +29,8 @@
cls.client = cls.availability_zone_client
@test.attr(type='gate')
+ @test.idempotent_id('a8333aa2-205c-449f-a828-d38c2489bf25')
def test_get_availability_zone_list_with_non_admin_user(self):
# List of availability zone with non-administrator user
- resp, availability_zone = self.client.get_availability_zone_list()
- self.assertEqual(200, resp.status)
+ availability_zone = self.client.get_availability_zone_list()
self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 85eb049..14eb536 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -43,18 +43,19 @@
'contents': base64.b64encode(file_contents)}]
cls.client = cls.servers_client
cls.network_client = cls.os.network_client
- cli_resp = cls.create_test_server(name=cls.name,
- meta=cls.meta,
- accessIPv4=cls.accessIPv4,
- accessIPv6=cls.accessIPv6,
- personality=personality,
- disk_config=cls.disk_config)
- cls.resp, cls.server_initial = cli_resp
+ disk_config = cls.disk_config
+ cls.server_initial = cls.create_test_server(name=cls.name,
+ meta=cls.meta,
+ accessIPv4=cls.accessIPv4,
+ accessIPv6=cls.accessIPv6,
+ personality=personality,
+ disk_config=disk_config)
cls.password = cls.server_initial['adminPass']
cls.client.wait_for_server_status(cls.server_initial['id'], 'ACTIVE')
- resp, cls.server = cls.client.get_server(cls.server_initial['id'])
+ cls.server = cls.client.get_server(cls.server_initial['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
def test_verify_server_details(self):
# Verify the specified server attributes are set correctly
self.assertEqual(self.accessIPv4, self.server['accessIPv4'])
@@ -68,21 +69,24 @@
self.assertEqual(self.meta, self.server['metadata'])
@test.attr(type='smoke')
+ @test.idempotent_id('9a438d88-10c6-4bcd-8b5b-5b6e25e1346f')
def test_list_servers(self):
# The created server should be in the list of all servers
- resp, body = self.client.list_servers()
+ body = self.client.list_servers()
servers = body['servers']
found = any([i for i in servers if i['id'] == self.server['id']])
self.assertTrue(found)
@test.attr(type='smoke')
+ @test.idempotent_id('585e934c-448e-43c4-acbf-d06a9b899997')
def test_list_servers_with_detail(self):
# The created server should be in the detailed list of all servers
- resp, body = self.client.list_servers_with_detail()
+ body = self.client.list_servers_with_detail()
servers = body['servers']
found = any([i for i in servers if i['id'] == self.server['id']])
self.assertTrue(found)
+ @test.idempotent_id('cbc0f52f-05aa-492b-bdc1-84b575ca294b')
@testtools.skipUnless(CONF.compute.run_ssh,
'Instance validation tests are disabled.')
@test.attr(type='gate')
@@ -94,6 +98,7 @@
self.password)
self.assertEqual(flavor['vcpus'], linux_client.get_number_of_vcpus())
+ @test.idempotent_id('ac1ad47f-984b-4441-9274-c9079b7a0666')
@testtools.skipUnless(CONF.compute.run_ssh,
'Instance validation tests are disabled.')
@test.attr(type='gate')
@@ -104,26 +109,25 @@
self.assertTrue(linux_client.hostname_equals_servername(self.name))
@test.attr(type='gate')
+ @test.idempotent_id('ed20d3fb-9d1f-4329-b160-543fbd5d9811')
def test_create_server_with_scheduler_hint_group(self):
# Create a server with the scheduler hint "group".
name = data_utils.rand_name('server_group')
policies = ['affinity']
- resp, body = self.client.create_server_group(name=name,
- policies=policies)
- self.assertEqual(200, resp.status)
+ body = self.client.create_server_group(name=name,
+ policies=policies)
group_id = body['id']
self.addCleanup(self.client.delete_server_group, group_id)
hints = {'group': group_id}
- resp, server = self.create_test_server(sched_hints=hints,
- wait_until='ACTIVE')
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(sched_hints=hints,
+ wait_until='ACTIVE')
# Check a server is in the group
- resp, server_group = self.client.get_server_group(group_id)
- self.assertEqual(200, resp.status)
+ server_group = self.client.get_server_group(group_id)
self.assertIn(server['id'], server_group['members'])
+ @test.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2')
@testtools.skipUnless(CONF.service_available.neutron,
'Neutron service must be available.')
def test_verify_multiple_nics_order(self):
@@ -156,7 +160,7 @@
networks = [{'uuid': net1['network']['id']},
{'uuid': net2['network']['id']}]
- _, server_multi_nics = self.create_test_server(
+ server_multi_nics = self.create_test_server(
networks=networks, wait_until='ACTIVE')
# Cleanup server; this is needed in the test case because with the LIFO
@@ -171,7 +175,7 @@
self.addCleanup(cleanup_server)
- _, addresses = self.client.list_addresses(server_multi_nics['id'])
+ addresses = self.client.list_addresses(server_multi_nics['id'])
# We can't predict the ip addresses assigned to the server on networks.
# Sometimes the assigned addresses are ['19.80.0.2', '19.86.0.2'], at
@@ -196,6 +200,7 @@
cls.flavor_client = cls.os_adm.flavors_client
cls.client = cls.servers_client
+ @test.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
@testtools.skipUnless(CONF.compute.run_ssh,
'Instance validation tests are disabled.')
@test.attr(type='gate')
@@ -245,22 +250,22 @@
admin_pass = self.image_ssh_password
- resp, server_no_eph_disk = (self.create_test_server(
- wait_until='ACTIVE',
- adminPass=admin_pass,
- flavor=flavor_no_eph_disk_id))
- resp, server_with_eph_disk = (self.create_test_server(
- wait_until='ACTIVE',
- adminPass=admin_pass,
- flavor=flavor_with_eph_disk_id))
+ server_no_eph_disk = (self.create_test_server(
+ wait_until='ACTIVE',
+ adminPass=admin_pass,
+ flavor=flavor_no_eph_disk_id))
+ server_with_eph_disk = (self.create_test_server(
+ wait_until='ACTIVE',
+ adminPass=admin_pass,
+ flavor=flavor_with_eph_disk_id))
# Get partition number of server without extra specs.
- _, server_no_eph_disk = self.client.get_server(
+ server_no_eph_disk = self.client.get_server(
server_no_eph_disk['id'])
linux_client = remote_client.RemoteClient(server_no_eph_disk,
self.ssh_user, admin_pass)
partition_num = len(linux_client.get_partitions().split('\n'))
- _, server_with_eph_disk = self.client.get_server(
+ server_with_eph_disk = self.client.get_server(
server_with_eph_disk['id'])
linux_client = remote_client.RemoteClient(server_with_eph_disk,
self.ssh_user, admin_pass)
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 9d1ea9e..8842899 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -33,63 +33,63 @@
cls.client = cls.servers_client
@test.attr(type='gate')
+ @test.idempotent_id('9e6e0c87-3352-42f7-9faf-5d6210dbd159')
def test_delete_server_while_in_building_state(self):
# Delete a server while it's VM state is Building
- resp, server = self.create_test_server(wait_until='BUILD')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ server = self.create_test_server(wait_until='BUILD')
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('925fdfb4-5b13-47ea-ac8a-c36ae6fddb05')
def test_delete_active_server(self):
# Delete a server while it's VM state is Active
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('546d368c-bb6c-4645-979a-83ed16f3a6be')
def test_delete_server_while_in_shutoff_state(self):
# Delete a server while it's VM state is Shutoff
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, body = self.client.stop(server['id'])
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.stop(server['id'])
self.client.wait_for_server_status(server['id'], 'SHUTOFF')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
+ @test.idempotent_id('943bd6e8-4d7a-4904-be83-7a6cc2d4213b')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type='gate')
def test_delete_server_while_in_pause_state(self):
# Delete a server while it's VM state is Pause
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, body = self.client.pause_server(server['id'])
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.pause_server(server['id'])
self.client.wait_for_server_status(server['id'], 'PAUSED')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
+ @test.idempotent_id('1f82ebd3-8253-4f4e-b93f-de9b7df56d8b')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type='gate')
def test_delete_server_while_in_suspended_state(self):
# Delete a server while it's VM state is Suspended
- _, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
self.client.suspend_server(server['id'])
self.client.wait_for_server_status(server['id'], 'SUSPENDED')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
+ @test.idempotent_id('bb0cb402-09dd-4947-b6e5-5e7e1cfa61ad')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type='gate')
def test_delete_server_while_in_shelved_state(self):
# Delete a server while it's VM state is Shelved
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, body = self.client.shelve_server(server['id'])
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.shelve_server(server['id'])
offload_time = CONF.compute.shelved_offload_time
if offload_time >= 0:
@@ -99,41 +99,39 @@
else:
self.client.wait_for_server_status(server['id'],
'SHELVED')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
+ @test.idempotent_id('ab0c38b4-cdd8-49d3-9b92-0cb898723c01')
@testtools.skipIf(not CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='gate')
def test_delete_server_while_in_verify_resize_state(self):
# Delete a server while it's VM state is VERIFY_RESIZE
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, body = self.client.resize(server['id'], self.flavor_ref_alt)
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.client.resize(server['id'], self.flavor_ref_alt)
self.client.wait_for_server_status(server['id'], 'VERIFY_RESIZE')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
+ @test.idempotent_id('d0f3f0d6-d9b6-4a32-8da4-23015dcab23c')
@test.services('volume')
@test.attr(type='gate')
def test_delete_server_while_in_attached_volume(self):
# Delete a server while a volume is attached to it
volumes_client = self.volumes_extensions_client
device = '/dev/%s' % CONF.compute.volume_device_name
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
- resp, volume = volumes_client.create_volume(1)
+ volume = volumes_client.create_volume(1)
self.addCleanup(volumes_client.delete_volume, volume['id'])
volumes_client.wait_for_volume_status(volume['id'], 'available')
- resp, body = self.client.attach_volume(server['id'],
- volume['id'],
- device=device)
+ self.client.attach_volume(server['id'],
+ volume['id'],
+ device=device)
volumes_client.wait_for_volume_status(volume['id'], 'in-use')
- resp, _ = self.client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
volumes_client.wait_for_volume_status(volume['id'], 'available')
@@ -149,23 +147,22 @@
cls.admin_client = cls.os_adm.servers_client
@test.attr(type='gate')
+ @test.idempotent_id('99774678-e072-49d1-9d2a-49a59bc56063')
def test_delete_server_while_in_error_state(self):
# Delete a server while it's VM state is error
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, body = self.admin_client.reset_state(server['id'], state='error')
- self.assertEqual(202, resp.status)
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.admin_client.reset_state(server['id'], state='error')
# Verify server's state
- resp, server = self.non_admin_client.get_server(server['id'])
+ server = self.non_admin_client.get_server(server['id'])
self.assertEqual(server['status'], 'ERROR')
- resp, _ = self.non_admin_client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ self.non_admin_client.delete_server(server['id'])
self.servers_client.wait_for_server_termination(server['id'],
ignore_error=True)
@test.attr(type='gate')
+ @test.idempotent_id('73177903-6737-4f27-a60c-379e8ae8cf48')
def test_admin_delete_servers_of_others(self):
# Administrator can delete servers of others
- resp, server = self.create_test_server(wait_until='ACTIVE')
- resp, _ = self.admin_client.delete_server(server['id'])
- self.assertEqual('204', resp['status'])
+ server = self.create_test_server(wait_until='ACTIVE')
+ self.admin_client.delete_server(server['id'])
self.servers_client.wait_for_server_termination(server['id'])
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index eeef0e5..a15a9b7 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -31,59 +31,61 @@
raise cls.skipException(msg)
super(ServerDiskConfigTestJSON, cls).resource_setup()
cls.client = cls.os.servers_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
def _update_server_with_disk_config(self, disk_config):
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
if disk_config != server['OS-DCF:diskConfig']:
- resp, server = self.client.update_server(self.server_id,
- disk_config=disk_config)
- self.assertEqual(200, resp.status)
+ server = self.client.update_server(self.server_id,
+ disk_config=disk_config)
self.client.wait_for_server_status(server['id'], 'ACTIVE')
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
@test.attr(type='gate')
+ @test.idempotent_id('bef56b09-2e8c-4883-a370-4950812f430e')
def test_rebuild_server_with_manual_disk_config(self):
# A server should be rebuilt using the manual disk config option
self._update_server_with_disk_config(disk_config='AUTO')
- resp, server = self.client.rebuild(self.server_id,
- self.image_ref_alt,
- disk_config='MANUAL')
+ server = self.client.rebuild(self.server_id,
+ self.image_ref_alt,
+ disk_config='MANUAL')
# Wait for the server to become active
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the specified attributes are set correctly
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
@test.attr(type='gate')
+ @test.idempotent_id('9c9fae77-4feb-402f-8450-bf1c8b609713')
def test_rebuild_server_with_auto_disk_config(self):
# A server should be rebuilt using the auto disk config option
self._update_server_with_disk_config(disk_config='MANUAL')
- resp, server = self.client.rebuild(self.server_id,
- self.image_ref_alt,
- disk_config='AUTO')
+ server = self.client.rebuild(self.server_id,
+ self.image_ref_alt,
+ disk_config='AUTO')
# Wait for the server to become active
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the specified attributes are set correctly
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
def _get_alternative_flavor(self):
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
if server['flavor']['id'] == self.flavor_ref:
return self.flavor_ref_alt
else:
return self.flavor_ref
+ @test.idempotent_id('414e7e93-45b5-44bc-8e03-55159c6bfc97')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='gate')
@@ -98,9 +100,10 @@
self.client.confirm_resize(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
self.assertEqual('AUTO', server['OS-DCF:diskConfig'])
+ @test.idempotent_id('693d16f3-556c-489a-8bac-3d0ca2490bad')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='gate')
@@ -115,20 +118,20 @@
self.client.confirm_resize(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
@test.attr(type='gate')
+ @test.idempotent_id('5ef18867-358d-4de9-b3c9-94d4ba35742f')
def test_update_server_from_auto_to_manual(self):
# A server should be updated from auto to manual disk config
self._update_server_with_disk_config(disk_config='AUTO')
# Update the disk_config attribute to manual
- resp, server = self.client.update_server(self.server_id,
- disk_config='MANUAL')
- self.assertEqual(200, resp.status)
+ server = self.client.update_server(self.server_id,
+ disk_config='MANUAL')
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the disk_config attribute is set correctly
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 80b2a69..b00221c 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -23,27 +23,27 @@
def resource_setup(cls):
super(InstanceActionsTestJSON, cls).resource_setup()
cls.client = cls.servers_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
- cls.request_id = resp['x-compute-request-id']
+ server = cls.create_test_server(wait_until='ACTIVE')
+ cls.request_id = server.response['x-compute-request-id']
cls.server_id = server['id']
@test.attr(type='gate')
+ @test.idempotent_id('77ca5cc5-9990-45e0-ab98-1de8fead201a')
def test_list_instance_actions(self):
# List actions of the provided server
- resp, body = self.client.reboot(self.server_id, 'HARD')
+ self.client.reboot(self.server_id, 'HARD')
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, body = self.client.list_instance_actions(self.server_id)
- self.assertEqual(200, resp.status)
+ body = self.client.list_instance_actions(self.server_id)
self.assertTrue(len(body) == 2, str(body))
self.assertTrue(any([i for i in body if i['action'] == 'create']))
self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
@test.attr(type='gate')
+ @test.idempotent_id('aacc71ca-1d70-4aa5-bbf6-0ff71470e43c')
def test_get_instance_action(self):
# Get the action details of the provided server
- resp, body = self.client.get_instance_action(self.server_id,
- self.request_id)
- self.assertEqual(200, resp.status)
+ body = self.client.get_instance_action(self.server_id,
+ self.request_id)
self.assertEqual(self.server_id, body['instance_uuid'])
self.assertEqual('create', body['action'])
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index e92f04c..a0064b2 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -25,19 +26,21 @@
def resource_setup(cls):
super(InstanceActionsNegativeTestJSON, cls).resource_setup()
cls.client = cls.servers_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('67e1fce6-7ec2-45c6-92d4-0a8f1a632910')
def test_list_instance_actions_non_existent_server(self):
# List actions of the non-existent server id
non_existent_server_id = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_instance_actions,
non_existent_server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0269f40a-6f18-456c-b336-c03623c897f1')
def test_get_instance_action_invalid_request(self):
# Get the action details of the provided server with invalid request
- self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
+ self.assertRaises(lib_exc.NotFound, self.client.get_instance_action,
self.server_id, '999')
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 375f441..bfba105 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -14,12 +14,12 @@
# under the License.
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
from tempest.api import utils
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -28,11 +28,19 @@
class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
cls.set_network_resources(network=True, subnet=True, dhcp=True)
- super(ListServerFiltersTestJSON, cls).resource_setup()
+ super(ListServerFiltersTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(ListServerFiltersTestJSON, cls).setup_clients()
cls.client = cls.servers_client
+ @classmethod
+ def resource_setup(cls):
+ super(ListServerFiltersTestJSON, cls).resource_setup()
+
# Check to see if the alternate image ref actually exists...
images_client = cls.images_client
images = images_client.list_images()
@@ -48,29 +56,29 @@
# not exist, fail early since the tests won't work...
try:
cls.images_client.get_image(cls.image_ref)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
raise RuntimeError("Image %s (image_ref) was not found!" %
cls.image_ref)
try:
cls.images_client.get_image(cls.image_ref_alt)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
raise RuntimeError("Image %s (image_ref_alt) was not found!" %
cls.image_ref_alt)
cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
- resp, cls.s1 = cls.create_test_server(name=cls.s1_name,
- wait_until='ACTIVE')
+ cls.s1 = cls.create_test_server(name=cls.s1_name,
+ wait_until='ACTIVE')
cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
- resp, cls.s2 = cls.create_test_server(name=cls.s2_name,
- image_id=cls.image_ref_alt,
- wait_until='ACTIVE')
+ cls.s2 = cls.create_test_server(name=cls.s2_name,
+ image_id=cls.image_ref_alt,
+ wait_until='ACTIVE')
cls.s3_name = data_utils.rand_name(cls.__name__ + '-instance')
- resp, cls.s3 = cls.create_test_server(name=cls.s3_name,
- flavor=cls.flavor_ref_alt,
- wait_until='ACTIVE')
+ cls.s3 = cls.create_test_server(name=cls.s3_name,
+ flavor=cls.flavor_ref_alt,
+ wait_until='ACTIVE')
cls.fixed_network_name = CONF.compute.fixed_network_name
if CONF.service_available.neutron:
@@ -78,12 +86,13 @@
network = cls.isolated_creds.get_primary_network()
cls.fixed_network_name = network['name']
+ @test.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
@utils.skip_unless_attr('multiple_images', 'Only one image found')
@test.attr(type='gate')
def test_list_servers_filter_by_image(self):
# Filter the list of servers by image
params = {'image': self.image_ref}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -91,10 +100,11 @@
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('573637f5-7325-47bb-9144-3476d0416908')
def test_list_servers_filter_by_flavor(self):
# Filter the list of servers by flavor
params = {'flavor': self.flavor_ref_alt}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -102,10 +112,11 @@
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('9b067a7b-7fee-4f6a-b29c-be43fe18fc5a')
def test_list_servers_filter_by_server_name(self):
# Filter the list of servers by server name
params = {'name': self.s1_name}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -113,10 +124,11 @@
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('ca78e20e-fddb-4ce6-b7f7-bcbf8605e66e')
def test_list_servers_filter_by_server_status(self):
# Filter the list of servers by server status
params = {'status': 'active'}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -124,13 +136,14 @@
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('451dbbb2-f330-4a9f-b0e1-5f5d2cb0f34c')
def test_list_servers_filter_by_shutoff_status(self):
# Filter the list of servers by server shutoff status
params = {'status': 'shutoff'}
self.client.stop(self.s1['id'])
self.client.wait_for_server_status(self.s1['id'],
'SHUTOFF')
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
self.client.start(self.s1['id'])
self.client.wait_for_server_status(self.s1['id'],
'ACTIVE')
@@ -141,28 +154,32 @@
self.assertNotIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('614cdfc1-d557-4bac-915b-3e67b48eee76')
def test_list_servers_filter_by_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 1}
- resp, servers = self.client.list_servers(params)
+ servers = self.client.list_servers(params)
self.assertEqual(1, len([x for x in servers['servers'] if 'id' in x]))
@test.attr(type='gate')
+ @test.idempotent_id('b1495414-2d93-414c-8019-849afe8d319e')
def test_list_servers_filter_by_zero_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 0}
- resp, servers = self.client.list_servers(params)
+ servers = self.client.list_servers(params)
self.assertEqual(0, len(servers['servers']))
@test.attr(type='gate')
+ @test.idempotent_id('37791bbd-90c0-4de0-831e-5f38cba9c6b3')
def test_list_servers_filter_by_exceed_limit(self):
# Verify only the expected number of servers are returned
params = {'limit': 100000}
- resp, servers = self.client.list_servers(params)
- resp, all_servers = self.client.list_servers()
+ servers = self.client.list_servers(params)
+ all_servers = self.client.list_servers()
self.assertEqual(len([x for x in all_servers['servers'] if 'id' in x]),
len([x for x in servers['servers'] if 'id' in x]))
+ @test.idempotent_id('b3304c3b-97df-46d2-8cd3-e2b6659724e7')
@utils.skip_unless_attr('multiple_images', 'Only one image found')
@test.attr(type='gate')
def test_list_servers_detailed_filter_by_image(self):
@@ -176,10 +193,11 @@
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('80c574cc-0925-44ba-8602-299028357dd9')
def test_list_servers_detailed_filter_by_flavor(self):
# Filter the detailed list of servers by flavor
params = {'flavor': self.flavor_ref_alt}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
self.assertNotIn(self.s1['id'], map(lambda x: x['id'], servers))
@@ -187,10 +205,11 @@
self.assertIn(self.s3['id'], map(lambda x: x['id'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('f9eb2b70-735f-416c-b260-9914ac6181e4')
def test_list_servers_detailed_filter_by_server_name(self):
# Filter the detailed list of servers by server name
params = {'name': self.s1_name}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -198,10 +217,11 @@
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('de2612ab-b7dd-4044-b0b1-d2539601911f')
def test_list_servers_detailed_filter_by_server_status(self):
# Filter the detailed list of servers by server status
params = {'status': 'active'}
- resp, body = self.client.list_servers_with_detail(params)
+ body = self.client.list_servers_with_detail(params)
servers = body['servers']
test_ids = [s['id'] for s in (self.s1, self.s2, self.s3)]
@@ -212,10 +232,11 @@
if x['id'] in test_ids])
@test.attr(type='gate')
+ @test.idempotent_id('e9f624ee-92af-4562-8bec-437945a18dcb')
def test_list_servers_filtered_by_name_wildcard(self):
# List all servers that contains '-instance' in name
params = {'name': '-instance'}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -226,7 +247,7 @@
part_name = self.s1_name[6:-1]
params = {'name': part_name}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -234,12 +255,13 @@
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('24a89b0c-0d55-4a28-847f-45075f19b27b')
def test_list_servers_filtered_by_name_regex(self):
# list of regex that should match s1, s2 and s3
regexes = ['^.*\-instance\-[0-9]+$', '^.*\-instance\-.*$']
for regex in regexes:
params = {'name': regex}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -250,7 +272,7 @@
part_name = self.s1_name[-10:]
params = {'name': part_name}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -258,13 +280,14 @@
self.assertNotIn(self.s3_name, map(lambda x: x['name'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('43a1242e-7b31-48d1-88f2-3f72aa9f2077')
def test_list_servers_filtered_by_ip(self):
# Filter servers by ip
# Here should be listed 1 server
- resp, self.s1 = self.client.get_server(self.s1['id'])
+ self.s1 = self.client.get_server(self.s1['id'])
ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
params = {'ip': ip}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -274,14 +297,15 @@
@decorators.skip_because(bug="1182883",
condition=CONF.service_available.neutron)
@test.attr(type='gate')
+ @test.idempotent_id('a905e287-c35e-42f2-b132-d02b09f3654a')
def test_list_servers_filtered_by_ip_regex(self):
# Filter servers by regex ip
# List all servers filtered by part of ip address.
# Here should be listed all servers
- resp, self.s1 = self.client.get_server(self.s1['id'])
+ self.s1 = self.client.get_server(self.s1['id'])
ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
params = {'ip': ip}
- resp, body = self.client.list_servers(params)
+ body = self.client.list_servers(params)
servers = body['servers']
self.assertIn(self.s1_name, map(lambda x: x['name'], servers))
@@ -289,8 +313,9 @@
self.assertIn(self.s3_name, map(lambda x: x['name'], servers))
@test.attr(type='gate')
+ @test.idempotent_id('67aec2d0-35fe-4503-9f92-f13272b867ed')
def test_list_servers_detailed_limit_results(self):
# Verify only the expected number of detailed results are returned
params = {'limit': 1}
- resp, servers = self.client.list_servers_with_detail(params)
+ servers = self.client.list_servers_with_detail(params)
self.assertEqual(1, len(servers['servers']))
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index fd66d2b..7837ac1 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -14,9 +14,9 @@
# under the License.
from six import moves
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -35,10 +35,10 @@
cls.existing_fixtures = []
cls.deleted_fixtures = []
for x in moves.xrange(2):
- resp, srv = cls.create_test_server(wait_until='ACTIVE')
+ srv = cls.create_test_server(wait_until='ACTIVE')
cls.existing_fixtures.append(srv)
- resp, srv = cls.create_test_server()
+ srv = cls.create_test_server()
cls.client.delete_server(srv['id'])
# We ignore errors on termination because the server may
# be put into ERROR status on a quick spawn, then delete,
@@ -49,101 +49,103 @@
cls.deleted_fixtures.append(srv)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('24a26f1a-1ddc-4eea-b0d7-a90cc874ad8f')
def test_list_servers_with_a_deleted_server(self):
# Verify deleted servers do not show by default in list servers
# List servers and verify server not returned
- resp, body = self.client.list_servers()
+ body = self.client.list_servers()
servers = body['servers']
deleted_ids = [s['id'] for s in self.deleted_fixtures]
actual = [srv for srv in servers
if srv['id'] in deleted_ids]
- self.assertEqual('200', resp['status'])
self.assertEqual([], actual)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ff01387d-c7ad-47b4-ae9e-64fa214638fe')
def test_list_servers_by_non_existing_image(self):
# Listing servers for a non existing image returns empty list
non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
- resp, body = self.client.list_servers(dict(image=non_existing_image))
+ body = self.client.list_servers(dict(image=non_existing_image))
servers = body['servers']
- self.assertEqual('200', resp['status'])
self.assertEqual([], servers)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5913660b-223b-44d4-a651-a0fbfd44ca75')
def test_list_servers_by_non_existing_flavor(self):
# Listing servers by non existing flavor returns empty list
non_existing_flavor = 1234
- resp, body = self.client.list_servers(dict(flavor=non_existing_flavor))
+ body = self.client.list_servers(dict(flavor=non_existing_flavor))
servers = body['servers']
- self.assertEqual('200', resp['status'])
self.assertEqual([], servers)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e2c77c4a-000a-4af3-a0bd-629a328bde7c')
def test_list_servers_by_non_existing_server_name(self):
# Listing servers for a non existent server name returns empty list
non_existing_name = 'junk_server_1234'
- resp, body = self.client.list_servers(dict(name=non_existing_name))
+ body = self.client.list_servers(dict(name=non_existing_name))
servers = body['servers']
- self.assertEqual('200', resp['status'])
self.assertEqual([], servers)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fcdf192d-0f74-4d89-911f-1ec002b822c4')
def test_list_servers_status_non_existing(self):
# Return an empty list when invalid status is specified
non_existing_status = 'BALONEY'
- resp, body = self.client.list_servers(dict(status=non_existing_status))
+ body = self.client.list_servers(dict(status=non_existing_status))
servers = body['servers']
- self.assertEqual('200', resp['status'])
self.assertEqual([], servers)
@test.attr(type='gate')
+ @test.idempotent_id('12c80a9f-2dec-480e-882b-98ba15757659')
def test_list_servers_by_limits(self):
# List servers by specifying limits
- resp, body = self.client.list_servers({'limit': 1})
- self.assertEqual('200', resp['status'])
- # when _interface='xml', one element for servers_links in servers
+ body = self.client.list_servers({'limit': 1})
self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d47c17fb-eebd-4287-8e95-f20a7e627b18')
def test_list_servers_by_limits_greater_than_actual_count(self):
# List servers by specifying a greater value for limit
- resp, body = self.client.list_servers({'limit': 100})
- self.assertEqual('200', resp['status'])
+ body = self.client.list_servers({'limit': 100})
self.assertEqual(len(self.existing_fixtures), len(body['servers']))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('679bc053-5e70-4514-9800-3dfab1a380a6')
def test_list_servers_by_limits_pass_string(self):
# Return an error if a string value is passed for limit
- self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
{'limit': 'testing'})
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('62610dd9-4713-4ee0-8beb-fd2c1aa7f950')
def test_list_servers_by_limits_pass_negative_value(self):
# Return an error if a negative value for limit is passed
- self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
{'limit': -1})
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('87d12517-e20a-4c9c-97b6-dd1628d6d6c9')
def test_list_servers_by_changes_since_invalid_date(self):
# Return an error when invalid date format is passed
- self.assertRaises(exceptions.BadRequest, self.client.list_servers,
+ self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
{'changes-since': '2011/01/01'})
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('74745ad8-b346-45b5-b9b8-509d7447fc1f')
def test_list_servers_by_changes_since_future_date(self):
# Return an empty list when a date in the future is passed
changes_since = {'changes-since': '2051-01-01T12:34:00Z'}
- resp, body = self.client.list_servers(changes_since)
- self.assertEqual('200', resp['status'])
+ body = self.client.list_servers(changes_since)
self.assertEqual(0, len(body['servers']))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('93055106-2d34-46fe-af68-d9ddbf7ee570')
def test_list_servers_detail_server_is_deleted(self):
# Server details are not listed for a deleted server
deleted_ids = [s['id'] for s in self.deleted_fixtures]
- resp, body = self.client.list_servers_with_detail()
+ body = self.client.list_servers_with_detail()
servers = body['servers']
actual = [srv for srv in servers
if srv['id'] in deleted_ids]
- self.assertEqual('200', resp['status'])
self.assertEqual([], actual)
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 6fd2a75..69c056e 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -30,26 +30,26 @@
created servers into the servers list to be cleaned up after all.
"""
kwargs['name'] = kwargs.get('name', self._generate_name())
- resp, body = self.create_test_server(**kwargs)
+ body = self.create_test_server(**kwargs)
- return resp, body
+ return body
@test.attr(type='gate')
+ @test.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
def test_multiple_create(self):
- resp, body = self._create_multiple_servers(wait_until='ACTIVE',
- min_count=1,
- max_count=2)
+ body = self._create_multiple_servers(wait_until='ACTIVE',
+ min_count=1,
+ max_count=2)
# NOTE(maurosr): do status response check and also make sure that
# reservation_id is not in the response body when the request send
# contains return_reservation_id=False
- self.assertEqual('202', resp['status'])
self.assertNotIn('reservation_id', body)
@test.attr(type='gate')
+ @test.idempotent_id('864777fb-2f1e-44e3-b5b9-3eb6fa84f2f7')
def test_multiple_create_with_reservation_return(self):
- resp, body = self._create_multiple_servers(wait_until='ACTIVE',
- min_count=1,
- max_count=2,
- return_reservation_id=True)
- self.assertEqual(resp['status'], '202')
+ body = self._create_multiple_servers(wait_until='ACTIVE',
+ min_count=1,
+ max_count=2,
+ return_reservation_id=True)
self.assertIn('reservation_id', body)
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index 55db605..caf1ae5 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -31,38 +32,43 @@
created servers into the servers list to be cleaned up after all.
"""
kwargs['name'] = kwargs.get('name', self._generate_name())
- resp, body = self.create_test_server(**kwargs)
+ body = self.create_test_server(**kwargs)
- return resp, body
+ return body
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('daf29d8d-e928-4a01-9a8c-b129603f3fc0')
def test_min_count_less_than_one(self):
invalid_min_count = 0
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
min_count=invalid_min_count)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('999aa722-d624-4423-b813-0d1ac9884d7a')
def test_min_count_non_integer(self):
invalid_min_count = 2.5
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
min_count=invalid_min_count)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a6f9c2ab-e060-4b82-b23c-4532cb9390ff')
def test_max_count_less_than_one(self):
invalid_max_count = 0
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
max_count=invalid_max_count)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9c5698d1-d7af-4c80-b971-9d403135eea2')
def test_max_count_non_integer(self):
invalid_max_count = 2.5
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
max_count=invalid_max_count)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('476da616-f1ef-4271-a9b1-b9fc87727cdf')
def test_max_count_less_than_min_count(self):
min_count = 3
max_count = 2
- self.assertRaises(exceptions.BadRequest, self._create_multiple_servers,
+ self.assertRaises(lib_exc.BadRequest, self._create_multiple_servers,
min_count=min_count,
max_count=max_count)
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 9edaede..ce3772f 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -18,13 +18,13 @@
import urlparse
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -47,7 +47,7 @@
self.__class__.server_id = self.rebuild_server(self.server_id)
def tearDown(self):
- _, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
self.assertEqual(self.image_ref, server['image']['id'])
self.server_check_teardown()
super(ServerActionsTestJSON, self).tearDown()
@@ -59,19 +59,19 @@
cls.client = cls.servers_client
cls.server_id = cls.rebuild_server(None)
+ @test.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
@testtools.skipUnless(CONF.compute_feature_enabled.change_password,
'Change password not available.')
@test.attr(type='gate')
def test_change_server_password(self):
# The server's password should be set to the provided password
new_password = 'Newpass1234'
- resp, body = self.client.change_password(self.server_id, new_password)
- self.assertEqual(202, resp.status)
+ self.client.change_password(self.server_id, new_password)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
if self.run_ssh:
# Verify that the user can authenticate with the new password
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
linux_client = remote_client.RemoteClient(server, self.ssh_user,
new_password)
linux_client.validate_authentication()
@@ -79,13 +79,12 @@
def _test_reboot_server(self, reboot_type):
if self.run_ssh:
# Get the time the server was last rebooted,
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
linux_client = remote_client.RemoteClient(server, self.ssh_user,
self.password)
boot_time = linux_client.get_boot_time()
- resp, body = self.client.reboot(self.server_id, reboot_type)
- self.assertEqual(202, resp.status)
+ self.client.reboot(self.server_id, reboot_type)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
if self.run_ssh:
@@ -97,17 +96,20 @@
'%s > %s' % (new_boot_time, boot_time))
@test.attr(type='smoke')
+ @test.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
def test_reboot_server_hard(self):
# The server should be power cycled
self._test_reboot_server('HARD')
@decorators.skip_because(bug="1014647")
@test.attr(type='smoke')
+ @test.idempotent_id('4640e3ef-a5df-482e-95a1-ceeeb0faa84d')
def test_reboot_server_soft(self):
# The server should be signaled to reboot gracefully
self._test_reboot_server('SOFT')
@test.attr(type='smoke')
+ @test.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
def test_rebuild_server(self):
# The server should be rebuilt using the provided image and data
meta = {'rebuild': 'server'}
@@ -116,12 +118,12 @@
personality = [{'path': 'rebuild.txt',
'contents': base64.b64encode(file_contents)}]
password = 'rebuildPassw0rd'
- resp, rebuilt_server = self.client.rebuild(self.server_id,
- self.image_ref_alt,
- name=new_name,
- metadata=meta,
- personality=personality,
- adminPass=password)
+ rebuilt_server = self.client.rebuild(self.server_id,
+ self.image_ref_alt,
+ name=new_name,
+ metadata=meta,
+ personality=personality,
+ adminPass=password)
# Verify the properties in the initial response are correct
self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -131,7 +133,7 @@
# Verify the server properties after the rebuild completes
self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
- resp, server = self.client.get_server(rebuilt_server['id'])
+ server = self.client.get_server(rebuilt_server['id'])
rebuilt_image_id = server['image']['id']
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
self.assertEqual(new_name, server['name'])
@@ -145,17 +147,17 @@
self.client.rebuild(self.server_id, self.image_ref)
@test.attr(type='gate')
+ @test.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d')
def test_rebuild_server_in_stop_state(self):
# The server in stop state should be rebuilt using the provided
# image and remain in SHUTOFF state
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
old_image = server['image']['id']
new_image = self.image_ref_alt \
if old_image == self.image_ref else self.image_ref
- resp, server = self.client.stop(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.stop(self.server_id)
self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
- resp, rebuilt_server = self.client.rebuild(self.server_id, new_image)
+ rebuilt_server = self.client.rebuild(self.server_id, new_image)
# Verify the properties in the initial response are correct
self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -165,7 +167,7 @@
# Verify the server properties after the rebuild completes
self.client.wait_for_server_status(rebuilt_server['id'], 'SHUTOFF')
- resp, server = self.client.get_server(rebuilt_server['id'])
+ server = self.client.get_server(rebuilt_server['id'])
rebuilt_image_id = server['image']['id']
self.assertEqual(new_image, rebuilt_image_id)
@@ -177,7 +179,7 @@
def _detect_server_image_flavor(self, server_id):
# Detects the current server image flavor ref.
- resp, server = self.client.get_server(server_id)
+ server = self.client.get_server(server_id)
current_flavor = server['flavor']['id']
new_flavor_ref = self.flavor_ref_alt \
if current_flavor == self.flavor_ref else self.flavor_ref
@@ -191,38 +193,39 @@
self._detect_server_image_flavor(self.server_id)
if stop:
- resp = self.servers_client.stop(self.server_id)[0]
- self.assertEqual(202, resp.status)
+ self.servers_client.stop(self.server_id)
self.servers_client.wait_for_server_status(self.server_id,
'SHUTOFF')
- resp, server = self.client.resize(self.server_id, new_flavor_ref)
- self.assertEqual(202, resp.status)
+ self.client.resize(self.server_id, new_flavor_ref)
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
self.client.confirm_resize(self.server_id)
expected_status = 'SHUTOFF' if stop else 'ACTIVE'
self.client.wait_for_server_status(self.server_id, expected_status)
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
self.assertEqual(new_flavor_ref, server['flavor']['id'])
if stop:
# NOTE(mriedem): tearDown requires the server to be started.
self.client.start(self.server_id)
+ @test.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='smoke')
def test_resize_server_confirm(self):
self._test_resize_server_confirm(stop=False)
+ @test.idempotent_id('138b131d-66df-48c9-a171-64f45eb92962')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='smoke')
def test_resize_server_confirm_from_stopped(self):
self._test_resize_server_confirm(stop=True)
+ @test.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type='gate')
@@ -233,16 +236,16 @@
previous_flavor_ref, new_flavor_ref = \
self._detect_server_image_flavor(self.server_id)
- resp, server = self.client.resize(self.server_id, new_flavor_ref)
- self.assertEqual(202, resp.status)
+ self.client.resize(self.server_id, new_flavor_ref)
self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
self.client.revert_resize(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
self.assertEqual(previous_flavor_ref, server['flavor']['id'])
+ @test.idempotent_id('b963d4f1-94b3-4c40-9e97-7b583f46e470')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting not available, backup not possible.')
@test.attr(type='gate')
@@ -251,10 +254,10 @@
# Positive test:create backup successfully and rotate backups correctly
# create the first and the second backup
backup1 = data_utils.rand_name('backup-1')
- resp, _ = self.servers_client.create_backup(self.server_id,
- 'daily',
- 2,
- backup1)
+ resp = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup1).response
oldest_backup_exist = True
# the oldest one should be deleted automatically in this test
@@ -262,7 +265,7 @@
if oldest_backup_exist:
try:
self.os.image_client.delete_image(oldest_backup)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
else:
LOG.warning("Deletion of oldest backup %s should not have "
@@ -271,18 +274,16 @@
image1_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(_clean_oldest_backup, image1_id)
- self.assertEqual(202, resp.status)
self.os.image_client.wait_for_image_status(image1_id, 'active')
backup2 = data_utils.rand_name('backup-2')
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, _ = self.servers_client.create_backup(self.server_id,
- 'daily',
- 2,
- backup2)
+ resp = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup2).response
image2_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image2_id)
- self.assertEqual(202, resp.status)
self.os.image_client.wait_for_image_status(image2_id, 'active')
# verify they have been created
@@ -304,13 +305,12 @@
# the first one will be deleted
backup3 = data_utils.rand_name('backup-3')
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
- resp, _ = self.servers_client.create_backup(self.server_id,
- 'daily',
- 2,
- backup3)
+ resp = self.servers_client.create_backup(self.server_id,
+ 'daily',
+ 2,
+ backup3).response
image3_id = data_utils.parse_image_id(resp['location'])
self.addCleanup(self.os.image_client.delete_image, image3_id)
- self.assertEqual(202, resp.status)
# the first back up should be deleted
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
self.os.image_client.wait_for_resource_deletion(image1_id)
@@ -329,13 +329,13 @@
(image_list[0]['name'], image_list[1]['name']))
def _get_output(self):
- resp, output = self.servers_client.get_console_output(
- self.server_id, 10)
- self.assertEqual(200, resp.status)
+ output = self.servers_client.get_console_output(
+ self.server_id, 10).data
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
self.assertEqual(lines, 10)
+ @test.idempotent_id('4b8867e6-fffa-4d54-b1d1-6fdda57be2f3')
@testtools.skipUnless(CONF.compute_feature_enabled.console_output,
'Console output not supported.')
@test.attr(type='gate')
@@ -348,21 +348,21 @@
# log file is truncated and we cannot get any console log through
# "console-log" API.
# The detail is https://bugs.launchpad.net/nova/+bug/1251920
- resp, body = self.servers_client.reboot(self.server_id, 'HARD')
- self.assertEqual(202, resp.status)
+ self.servers_client.reboot(self.server_id, 'HARD')
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
self.wait_for(self._get_output)
+ @test.idempotent_id('89104062-69d8-4b19-a71b-f47b7af093d7')
@testtools.skipUnless(CONF.compute_feature_enabled.console_output,
'Console output not supported.')
@test.attr(type='gate')
def test_get_console_output_with_unlimited_size(self):
- _, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
def _check_full_length_console_log():
- _, output = self.servers_client.get_console_output(server['id'],
- None)
+ output = self.servers_client.get_console_output(server['id'],
+ None).data
self.assertTrue(output, "Console output was empty.")
lines = len(output.split('\n'))
@@ -373,6 +373,7 @@
self.wait_for(_check_full_length_console_log)
+ @test.idempotent_id('5b65d4e7-4ecd-437c-83c0-d6b79d927568')
@testtools.skipUnless(CONF.compute_feature_enabled.console_output,
'Console output not supported.')
@test.attr(type='gate')
@@ -383,43 +384,40 @@
# NOTE: SHUTOFF is irregular status. To avoid test instability,
# one server is created only for this test without using
# the server that was created in setupClass.
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
temp_server_id = server['id']
- resp, server = self.servers_client.stop(temp_server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.stop(temp_server_id)
self.servers_client.wait_for_server_status(temp_server_id, 'SHUTOFF')
self.wait_for(self._get_output)
+ @test.idempotent_id('bd61a9fd-062f-4670-972b-2d6c3e3b9e73')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type='gate')
def test_pause_unpause_server(self):
- resp, server = self.client.pause_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.pause_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'PAUSED')
- resp, server = self.client.unpause_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.unpause_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+ @test.idempotent_id('0d8ee21e-b749-462d-83da-b85b41c86c7f')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type='gate')
def test_suspend_resume_server(self):
- resp, server = self.client.suspend_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.suspend_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
- resp, server = self.client.resume_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.resume_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+ @test.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type='gate')
def test_shelve_unshelve_server(self):
- resp, server = self.client.shelve_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.shelve_server(self.server_id)
offload_time = CONF.compute.shelved_offload_time
if offload_time >= 0:
@@ -430,49 +428,42 @@
self.client.wait_for_server_status(self.server_id,
'SHELVED')
- resp, server = self.client.shelve_offload_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.shelve_offload_server(self.server_id)
self.client.wait_for_server_status(self.server_id,
'SHELVED_OFFLOADED')
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
image_name = server['name'] + '-shelved'
params = {'name': image_name}
images = self.images_client.list_images(params)
self.assertEqual(1, len(images))
self.assertEqual(image_name, images[0]['name'])
- resp, server = self.client.unshelve_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.unshelve_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'ACTIVE')
@test.attr(type='gate')
+ @test.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
def test_stop_start_server(self):
- resp, server = self.servers_client.stop(self.server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.stop(self.server_id)
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
- resp, server = self.servers_client.start(self.server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.start(self.server_id)
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
@test.attr(type='gate')
+ @test.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
def test_lock_unlock_server(self):
# Lock the server,try server stop(exceptions throw),unlock it and retry
- resp, server = self.servers_client.lock_server(self.server_id)
- self.assertEqual(202, resp.status)
- resp, server = self.servers_client.get_server(self.server_id)
- self.assertEqual(200, resp.status)
+ self.servers_client.lock_server(self.server_id)
+ server = self.servers_client.get_server(self.server_id)
self.assertEqual(server['status'], 'ACTIVE')
# Locked server is not allowed to be stopped by non-admin user
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.servers_client.stop, self.server_id)
- resp, server = self.servers_client.unlock_server(self.server_id)
- self.assertEqual(202, resp.status)
- resp, server = self.servers_client.stop(self.server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.unlock_server(self.server_id)
+ self.servers_client.stop(self.server_id)
self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
- resp, server = self.servers_client.start(self.server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.start(self.server_id)
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
def _validate_url(self, url):
@@ -482,6 +473,7 @@
self.assertNotEqual('None', parsed_url.hostname)
self.assertIn(parsed_url.scheme, valid_scheme)
+ @test.idempotent_id('c6bc11bf-592e-4015-9319-1c98dc64daf5')
@testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
'VNC Console feature is disabled.')
@test.attr(type='gate')
@@ -489,11 +481,8 @@
# Get the VNC console of type 'novnc' and 'xvpvnc'
console_types = ['novnc', 'xvpvnc']
for console_type in console_types:
- resp, body = self.servers_client.get_vnc_console(self.server_id,
- console_type)
- self.assertEqual(
- 200, resp.status,
- "Failed to get Console Type: %s" % (console_types))
+ body = self.servers_client.get_vnc_console(self.server_id,
+ console_type)
self.assertEqual(console_type, body['type'])
self.assertNotEqual('', body['url'])
self._validate_url(body['url'])
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 3d1d964..d0dfc87 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -20,22 +20,30 @@
class ServerAddressesTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
# This test module might use a network and a subnet
cls.set_network_resources(network=True, subnet=True)
- super(ServerAddressesTestJSON, cls).resource_setup()
+ super(ServerAddressesTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(ServerAddressesTestJSON, cls).setup_clients()
cls.client = cls.servers_client
- resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
+ @classmethod
+ def resource_setup(cls):
+ super(ServerAddressesTestJSON, cls).resource_setup()
+
+ cls.server = cls.create_test_server(wait_until='ACTIVE')
@test.attr(type='smoke')
+ @test.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
@test.services('network')
def test_list_server_addresses(self):
# All public and private addresses for
# a server should be returned
- resp, addresses = self.client.list_addresses(self.server['id'])
- self.assertEqual('200', resp['status'])
+ addresses = self.client.list_addresses(self.server['id'])
# We do not know the exact network configuration, but an instance
# should at least have a single public or private address
@@ -47,20 +55,20 @@
self.assertTrue(address['version'])
@test.attr(type='smoke')
+ @test.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
@test.services('network')
def test_list_server_addresses_by_network(self):
# Providing a network type should filter
# the addresses return by that type
- resp, addresses = self.client.list_addresses(self.server['id'])
+ addresses = self.client.list_addresses(self.server['id'])
# Once again we don't know the environment's exact network config,
# but the response for each individual network should be the same
# as the partial result of the full address list
id = self.server['id']
for addr_type in addresses:
- resp, addr = self.client.list_addresses_by_network(id, addr_type)
- self.assertEqual('200', resp['status'])
+ addr = self.client.list_addresses_by_network(id, addr_type)
addr = addr[addr_type]
for address in addresses[addr_type]:
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index 3087e59..dac5637 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -13,32 +13,42 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
class ServerAddressesNegativeTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
cls.set_network_resources(network=True, subnet=True)
- super(ServerAddressesNegativeTestJSON, cls).resource_setup()
+ super(ServerAddressesNegativeTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(ServerAddressesNegativeTestJSON, cls).setup_clients()
cls.client = cls.servers_client
- resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
+ @classmethod
+ def resource_setup(cls):
+ super(ServerAddressesNegativeTestJSON, cls).resource_setup()
+ cls.server = cls.create_test_server(wait_until='ACTIVE')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
@test.services('network')
def test_list_server_addresses_invalid_server_id(self):
# List addresses request should fail if server id not in system
- self.assertRaises(exceptions.NotFound, self.client.list_addresses,
+ self.assertRaises(lib_exc.NotFound, self.client.list_addresses,
'999')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
@test.services('network')
def test_list_server_addresses_by_network_neg(self):
# List addresses by network should fail if network name not valid
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_addresses_by_network,
self.server['id'], 'invalid')
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index fe5dca0..ac04feb 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -37,26 +37,23 @@
server_group_name = data_utils.rand_name('server-group')
cls.policy = ['affinity']
- _, cls.created_server_group = cls.create_test_server_group(
+ cls.created_server_group = cls.create_test_server_group(
server_group_name,
cls.policy)
def _create_server_group(self, name, policy):
# create the test server-group with given policy
server_group = {'name': name, 'policies': policy}
- resp, body = self.create_test_server_group(name, policy)
- self.assertEqual(200, resp.status)
+ body = self.create_test_server_group(name, policy)
for key in ['name', 'policies']:
self.assertEqual(server_group[key], body[key])
return body
def _delete_server_group(self, server_group):
# delete the test server-group
- resp, _ = self.client.delete_server_group(server_group['id'])
- self.assertEqual(204, resp.status)
+ self.client.delete_server_group(server_group['id'])
# validation of server-group deletion
- resp, server_group_list = self.client.list_server_groups()
- self.assertEqual(200, resp.status)
+ server_group_list = self.client.list_server_groups()
self.assertNotIn(server_group, server_group_list)
def _create_delete_server_group(self, policy):
@@ -66,11 +63,13 @@
self._delete_server_group(server_group)
@test.attr(type='gate')
+ @test.idempotent_id('5dc57eda-35b7-4af7-9e5f-3c2be3d2d68b')
def test_create_delete_server_group_with_affinity_policy(self):
# Create and Delete the server-group with affinity policy
self._create_delete_server_group(self.policy)
@test.attr(type='gate')
+ @test.idempotent_id('3645a102-372f-4140-afad-13698d850d23')
def test_create_delete_server_group_with_anti_affinity_policy(self):
# Create and Delete the server-group with anti-affinity policy
policy = ['anti-affinity']
@@ -78,12 +77,14 @@
@decorators.skip_because(bug="1324348")
@test.attr(type='gate')
+ @test.idempotent_id('6d9bae05-eb32-425d-a673-e14e1b1c6306')
def test_create_delete_server_group_with_multiple_policies(self):
# Create and Delete the server-group with multiple policies
policies = ['affinity', 'affinity']
self._create_delete_server_group(policies)
@test.attr(type='gate')
+ @test.idempotent_id('154dc5a4-a2fe-44b5-b99e-f15806a4a113')
def test_create_delete_multiple_server_groups_with_same_name_policy(self):
# Create and Delete the server-groups with same name and same policy
server_groups = []
@@ -99,16 +100,16 @@
self._delete_server_group(server_groups[i])
@test.attr(type='gate')
+ @test.idempotent_id('b3545034-dd78-48f0-bdc2-a4adfa6d0ead')
def test_get_server_group(self):
# Get the server-group
- resp, body = self.client.get_server_group(
+ body = self.client.get_server_group(
self.created_server_group['id'])
- self.assertEqual(200, resp.status)
self.assertEqual(self.created_server_group, body)
@test.attr(type='gate')
+ @test.idempotent_id('d4874179-27b4-4d7d-80e4-6c560cdfe321')
def test_list_server_groups(self):
# List the server-group
- resp, body = self.client.list_server_groups()
- self.assertEqual(200, resp.status)
+ body = self.client.list_server_groups()
self.assertIn(self.created_server_group, body)
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index 6fd6a6d..4a14228 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -24,92 +24,88 @@
super(ServerMetadataTestJSON, cls).resource_setup()
cls.client = cls.servers_client
cls.quotas = cls.quotas_client
- resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(meta={}, wait_until='ACTIVE')
cls.server_id = server['id']
def setUp(self):
super(ServerMetadataTestJSON, self).setUp()
meta = {'key1': 'value1', 'key2': 'value2'}
- resp, _ = self.client.set_server_metadata(self.server_id, meta)
- self.assertEqual(resp.status, 200)
+ self.client.set_server_metadata(self.server_id, meta)
@test.attr(type='gate')
+ @test.idempotent_id('479da087-92b3-4dcf-aeb3-fd293b2d14ce')
def test_list_server_metadata(self):
# All metadata key/value pairs for a server should be returned
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
# Verify the expected metadata items are in the list
- self.assertEqual(200, resp.status)
expected = {'key1': 'value1', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('211021f6-21de-4657-a68f-908878cfe251')
def test_set_server_metadata(self):
# The server's metadata should be replaced with the provided values
# Create a new set of metadata for the server
req_metadata = {'meta2': 'data2', 'meta3': 'data3'}
- resp, metadata = self.client.set_server_metadata(self.server_id,
- req_metadata)
- self.assertEqual(200, resp.status)
+ self.client.set_server_metadata(self.server_id, req_metadata)
# Verify the expected values are correct, and that the
# previous values have been removed
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
self.assertEqual(resp_metadata, req_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('344d981e-0c33-4997-8a5d-6c1d803e4134')
def test_update_server_metadata(self):
# The server's metadata values should be updated to the
# provided values
meta = {'key1': 'alt1', 'key3': 'value3'}
- resp, metadata = self.client.update_server_metadata(self.server_id,
- meta)
- self.assertEqual(200, resp.status)
+ self.client.update_server_metadata(self.server_id, meta)
# Verify the values have been updated to the proper values
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('0f58d402-e34a-481d-8af8-b392b17426d9')
def test_update_metadata_empty_body(self):
# The original metadata should not be lost if empty metadata body is
# passed
meta = {}
- _, metadata = self.client.update_server_metadata(self.server_id, meta)
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ self.client.update_server_metadata(self.server_id, meta)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
expected = {'key1': 'value1', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('3043c57d-7e0e-49a6-9a96-ad569c265e6a')
def test_get_server_metadata_item(self):
# The value for a specific metadata key should be returned
- resp, meta = self.client.get_server_metadata_item(self.server_id,
- 'key2')
+ meta = self.client.get_server_metadata_item(self.server_id, 'key2')
self.assertEqual('value2', meta['key2'])
@test.attr(type='gate')
+ @test.idempotent_id('58c02d4f-5c67-40be-8744-d3fa5982eb1c')
def test_set_server_metadata_item(self):
# The item's value should be updated to the provided value
# Update the metadata value
meta = {'nova': 'alt'}
- resp, body = self.client.set_server_metadata_item(self.server_id,
- 'nova', meta)
- self.assertEqual(200, resp.status)
+ self.client.set_server_metadata_item(self.server_id, 'nova', meta)
# Verify the meta item's value has been updated
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
expected = {'key1': 'value1', 'key2': 'value2', 'nova': 'alt'}
self.assertEqual(expected, resp_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('127642d6-4c7b-4486-b7cd-07265a378658')
def test_delete_server_metadata_item(self):
# The metadata value/key pair should be deleted from the server
- resp, meta = self.client.delete_server_metadata_item(self.server_id,
- 'key1')
- self.assertEqual(204, resp.status)
+ self.client.delete_server_metadata_item(self.server_id, 'key1')
# Verify the metadata item has been removed
- resp, resp_metadata = self.client.list_server_metadata(self.server_id)
+ resp_metadata = self.client.list_server_metadata(self.server_id)
expected = {'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index e193677..0eb3800 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -13,9 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -27,11 +28,12 @@
cls.client = cls.servers_client
cls.quotas = cls.quotas_client
cls.tenant_id = cls.client.tenant_id
- resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
+ server = cls.create_test_server(meta={}, wait_until='ACTIVE')
cls.server_id = server['id']
@test.attr(type=['gate', 'negative'])
+ @test.idempotent_id('fe114a8f-3a57-4eff-9ee2-4e14628df049')
def test_server_create_metadata_key_too_long(self):
# Attempt to start a server with a meta-data key that is > 255
# characters
@@ -40,84 +42,93 @@
for sz in [256, 257, 511, 1023]:
key = "k" * sz
meta = {key: 'data1'}
- self.assertRaises((exceptions.BadRequest, exceptions.OverLimit),
+ self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
meta=meta)
# no teardown - all creates should fail
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('92431555-4d8b-467c-b95b-b17daa5e57ff')
def test_create_server_metadata_blank_key(self):
# Blank key should trigger an error.
meta = {'': 'data1'}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
meta=meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
def test_server_metadata_non_existent_server(self):
# GET on a non-existent server should not succeed
non_existent_server_id = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_server_metadata_item,
non_existent_server_id,
'test2')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f408e78e-3066-4097-9299-3b0182da812e')
def test_list_server_metadata_non_existent_server(self):
# List metadata on a non-existent server should not succeed
non_existent_server_id = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_server_metadata,
non_existent_server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0025fbd6-a4ba-4cde-b8c2-96805dcfdabc')
def test_wrong_key_passed_in_body(self):
# Raise BadRequest if key in uri does not match
# the key passed in body.
meta = {'testkey': 'testvalue'}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.set_server_metadata_item,
self.server_id, 'key', meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0df38c2a-3d4e-4db5-98d8-d4d9fa843a12')
def test_set_metadata_non_existent_server(self):
# Set metadata on a non-existent server should not succeed
non_existent_server_id = data_utils.rand_uuid()
meta = {'meta1': 'data1'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.set_server_metadata,
non_existent_server_id,
meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('904b13dc-0ef2-4e4c-91cd-3b4a0f2f49d8')
def test_update_metadata_non_existent_server(self):
# An update should not happen for a non-existent server
non_existent_server_id = data_utils.rand_uuid()
meta = {'key1': 'value1', 'key2': 'value2'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_server_metadata,
non_existent_server_id,
meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a452f38c-05c2-4b47-bd44-a4f0bf5a5e48')
def test_update_metadata_with_blank_key(self):
# Blank key should trigger an error
meta = {'': 'data1'}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_server_metadata,
self.server_id, meta=meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6bbd88e1-f8b3-424d-ba10-ae21c45ada8d')
def test_delete_metadata_non_existent_server(self):
# Should not be able to delete metadata item from a non-existent server
non_existent_server_id = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_server_metadata_item,
non_existent_server_id,
'd')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d8c0a210-a5c3-4664-be04-69d96746b547')
def test_metadata_items_limit(self):
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised while exceeding metadata items limit for
@@ -130,31 +141,33 @@
req_metadata = {}
for num in range(1, quota_metadata + 2):
req_metadata['key' + str(num)] = 'val' + str(num)
- self.assertRaises((exceptions.OverLimit, exceptions.Unauthorized),
+ self.assertRaises((lib_exc.OverLimit, lib_exc.Unauthorized),
self.client.set_server_metadata,
self.server_id, req_metadata)
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised while exceeding metadata items limit for
# tenant.
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.client.update_server_metadata,
self.server_id, req_metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
def test_set_server_metadata_blank_key(self):
# Raise a bad request error for blank key.
# set_server_metadata will replace all metadata with new value
meta = {'': 'data1'}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.set_server_metadata,
self.server_id, meta=meta)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('64a91aee-9723-4863-be44-4c9d9f1e7d0e')
def test_set_server_metadata_missing_metadata(self):
# Raise a bad request error for a missing metadata field
# set_server_metadata will replace all metadata with new value
meta = {'meta1': 'data1'}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.set_server_metadata,
self.server_id, meta=meta, no_metadata_field=True)
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index 994caa4..57fa408 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -24,14 +24,14 @@
def resource_setup(cls):
super(ServerPasswordTestJSON, cls).resource_setup()
cls.client = cls.servers_client
- resp, cls.server = cls.create_test_server(wait_until="ACTIVE")
+ cls.server = cls.create_test_server(wait_until="ACTIVE")
@test.attr(type='gate')
+ @test.idempotent_id('f83b582f-62a8-4f22-85b0-0dee50ff783a')
def test_get_server_password(self):
- resp, body = self.client.get_password(self.server['id'])
- self.assertEqual(200, resp.status)
+ self.client.get_password(self.server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('f8229e8b-b625-4493-800a-bde86ac611ea')
def test_delete_server_password(self):
- resp, body = self.client.delete_password(self.server['id'])
- self.assertEqual(204, resp.status)
+ self.client.delete_password(self.server['id'])
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index c6d48bc..4a28dfb 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -14,9 +14,9 @@
# under the License.
import base64
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
@@ -29,6 +29,7 @@
cls.user_client = cls.limits_client
@test.attr(type='gate')
+ @test.idempotent_id('176cd8c9-b9e8-48ee-a480-180beab292bf')
def test_personality_files_exceed_limit(self):
# Server creation should fail if greater than the maximum allowed
# number of files are injected into the server.
@@ -44,10 +45,11 @@
'contents': base64.b64encode(file_contents)})
# A 403 Forbidden or 413 Overlimit (old behaviour) exception
# will be raised when out of quota
- self.assertRaises((exceptions.Unauthorized, exceptions.OverLimit),
+ self.assertRaises((lib_exc.Unauthorized, lib_exc.OverLimit),
self.create_test_server, personality=personality)
@test.attr(type='gate')
+ @test.idempotent_id('52f12ee8-5180-40cc-b417-31572ea3d555')
def test_can_create_server_with_max_number_personality_files(self):
# Server should be created successfully if maximum allowed number of
# files is injected into the server during creation.
@@ -63,5 +65,4 @@
'path': path,
'contents': base64.b64encode(file_contents),
})
- resp, server = self.create_test_server(personality=person)
- self.assertEqual('202', resp['status'])
+ self.create_test_server(personality=person)
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index b04fe69..a1a99a1 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -24,16 +24,23 @@
class ServerRescueTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(ServerRescueTestJSON, cls).skip_checks()
if not CONF.compute_feature_enabled.rescue:
msg = "Server rescue not available."
raise cls.skipException(msg)
+ @classmethod
+ def setup_credentials(cls):
cls.set_network_resources(network=True, subnet=True, router=True)
+ super(ServerRescueTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def resource_setup(cls):
super(ServerRescueTestJSON, cls).resource_setup()
# Floating IP creation
- resp, body = cls.floating_ips_client.create_floating_ip()
+ body = cls.floating_ips_client.create_floating_ip()
cls.floating_ip_id = str(body['id']).strip()
cls.floating_ip = str(body['ip']).strip()
@@ -46,7 +53,7 @@
cls.sg_id = cls.sg['id']
# Server for positive tests
- resp, server = cls.create_test_server(wait_until='BUILD')
+ server = cls.create_test_server(wait_until='BUILD')
cls.server_id = server['id']
cls.password = server['adminPass']
cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
@@ -66,21 +73,20 @@
super(ServerRescueTestJSON, self).tearDown()
def _unrescue(self, server_id):
- resp, body = self.servers_client.unrescue_server(server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.unrescue_server(server_id)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
@test.attr(type='smoke')
+ @test.idempotent_id('fd032140-714c-42e4-a8fd-adcd8df06be6')
def test_rescue_unrescue_instance(self):
- resp, body = self.servers_client.rescue_server(
+ self.servers_client.rescue_server(
self.server_id, adminPass=self.password)
- self.assertEqual(200, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
- resp, body = self.servers_client.unrescue_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.unrescue_server(self.server_id)
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
@test.attr(type='gate')
+ @test.idempotent_id('4842e0cf-e87d-4d9d-b61f-f4791da3cacc')
def test_rescued_vm_associate_dissociate_floating_ip(self):
# Rescue the server
self.servers_client.rescue_server(
@@ -90,17 +96,15 @@
# Association of floating IP to a rescued vm
client = self.floating_ips_client
- resp, body = client.associate_floating_ip_to_server(self.floating_ip,
- self.server_id)
- self.assertEqual(202, resp.status)
+ client.associate_floating_ip_to_server(self.floating_ip,
+ self.server_id)
# Disassociation of floating IP that was associated in this method
- resp, body = \
- client.disassociate_floating_ip_from_server(self.floating_ip,
- self.server_id)
- self.assertEqual(202, resp.status)
+ client.disassociate_floating_ip_from_server(self.floating_ip,
+ self.server_id)
@test.attr(type='gate')
+ @test.idempotent_id('affca41f-7195-492d-8065-e09eee245404')
def test_rescued_vm_add_remove_security_group(self):
# Rescue the server
self.servers_client.rescue_server(
@@ -109,11 +113,8 @@
self.addCleanup(self._unrescue, self.server_id)
# Add Security group
- resp, body = self.servers_client.add_security_group(self.server_id,
- self.sg_name)
- self.assertEqual(202, resp.status)
+ self.servers_client.add_security_group(self.server_id, self.sg_name)
# Delete Security group
- resp, body = self.servers_client.remove_security_group(self.server_id,
- self.sg_name)
- self.assertEqual(202, resp.status)
+ self.servers_client.remove_security_group(self.server_id,
+ self.sg_name)
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index f1e2f7f..6e23334 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -12,12 +12,13 @@
# 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 import exceptions as lib_exc
import testtools
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -26,18 +27,25 @@
class ServerRescueNegativeTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(ServerRescueNegativeTestJSON, cls).skip_checks()
if not CONF.compute_feature_enabled.rescue:
msg = "Server rescue not available."
raise cls.skipException(msg)
+ @classmethod
+ def setup_credentials(cls):
cls.set_network_resources(network=True, subnet=True, router=True)
+ super(ServerRescueNegativeTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def resource_setup(cls):
super(ServerRescueNegativeTestJSON, cls).resource_setup()
cls.device = CONF.compute.volume_device_name
# Server for negative tests
- resp, server = cls.create_test_server(wait_until='BUILD')
- resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='BUILD')
+ resc_server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
cls.password = server['adminPass']
cls.rescue_id = resc_server['id']
@@ -49,7 +57,7 @@
cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
def _create_volume(self):
- resp, volume = self.volumes_extensions_client.create_volume(
+ volume = self.volumes_extensions_client.create_volume(
1, display_name=data_utils.rand_name(
self.__class__.__name__ + '_volume'))
self.addCleanup(self.delete_volume, volume['id'])
@@ -63,48 +71,50 @@
'available')
def _unrescue(self, server_id):
- resp, body = self.servers_client.unrescue_server(server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.unrescue_server(server_id)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
def _unpause(self, server_id):
- resp, body = self.servers_client.unpause_server(server_id)
- self.assertEqual(202, resp.status)
+ self.servers_client.unpause_server(server_id)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+ @test.idempotent_id('cc3a883f-43c0-4fb6-a9bb-5579d64984ed')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type=['negative', 'gate'])
def test_rescue_paused_instance(self):
# Rescue a paused server
- resp, body = self.servers_client.pause_server(self.server_id)
+ self.servers_client.pause_server(self.server_id)
self.addCleanup(self._unpause, self.server_id)
- self.assertEqual(202, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'PAUSED')
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.servers_client.rescue_server,
self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('db22b618-f157-4566-a317-1b6d467a8094')
def test_rescued_vm_reboot(self):
- self.assertRaises(exceptions.Conflict, self.servers_client.reboot,
+ self.assertRaises(lib_exc.Conflict, self.servers_client.reboot,
self.rescue_id, 'HARD')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
def test_rescue_non_existent_server(self):
# Rescue a non-existing server
non_existent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.servers_client.rescue_server,
non_existent_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('70cdb8a1-89f8-437d-9448-8844fd82bf46')
def test_rescued_vm_rebuild(self):
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.servers_client.rebuild,
self.rescue_id,
self.image_ref_alt)
+ @test.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
@test.services('volume')
@test.attr(type=['negative', 'gate'])
def test_rescued_vm_attach_volume(self):
@@ -117,12 +127,13 @@
self.addCleanup(self._unrescue, self.server_id)
# Attach the volume to the server
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.servers_client.attach_volume,
self.server_id,
volume['id'],
device='/dev/%s' % self.device)
+ @test.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
@test.services('volume')
@test.attr(type=['negative', 'gate'])
def test_rescued_vm_detach_volume(self):
@@ -144,7 +155,7 @@
self.addCleanup(self._unrescue, self.server_id)
# Detach the volume from the server expecting failure
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.servers_client.detach_volume,
self.server_id,
volume['id'])
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index d31b320..624d9c2 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -30,97 +30,101 @@
super(ServersTestJSON, self).tearDown()
@test.attr(type='gate')
+ @test.idempotent_id('b92d5ec7-b1dd-44a2-87e4-45e888c46ef0')
def test_create_server_with_admin_password(self):
# If an admin password is provided on server creation, the server's
# root password should be set to that password.
- resp, server = self.create_test_server(adminPass='testpassword')
+ server = self.create_test_server(adminPass='testpassword')
# Verify the password is set correctly in the response
self.assertEqual('testpassword', server['adminPass'])
@test.attr(type='gate')
+ @test.idempotent_id('8fea6be7-065e-47cf-89b8-496e6f96c699')
def test_create_with_existing_server_name(self):
# Creating a server with a name that already exists is allowed
# TODO(sdague): clear out try, we do cleanup one layer up
server_name = data_utils.rand_name('server')
- resp, server = self.create_test_server(name=server_name,
- wait_until='ACTIVE')
+ server = self.create_test_server(name=server_name,
+ wait_until='ACTIVE')
id1 = server['id']
- resp, server = self.create_test_server(name=server_name,
- wait_until='ACTIVE')
+ server = self.create_test_server(name=server_name,
+ wait_until='ACTIVE')
id2 = server['id']
self.assertNotEqual(id1, id2, "Did not create a new server")
- resp, server = self.client.get_server(id1)
+ server = self.client.get_server(id1)
name1 = server['name']
- resp, server = self.client.get_server(id2)
+ server = self.client.get_server(id2)
name2 = server['name']
self.assertEqual(name1, name2)
@test.attr(type='gate')
+ @test.idempotent_id('f9e15296-d7f9-4e62-b53f-a04e89160833')
def test_create_specify_keypair(self):
# Specify a keypair while creating a server
key_name = data_utils.rand_name('key')
self.keypairs_client.create_keypair(key_name)
self.keypairs_client.list_keypairs()
- resp, server = self.create_test_server(key_name=key_name)
- self.assertEqual('202', resp['status'])
+ server = self.create_test_server(key_name=key_name)
self.client.wait_for_server_status(server['id'], 'ACTIVE')
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual(key_name, server['key_name'])
def _update_server_name(self, server_id, status):
# The server name should be changed to the the provided value
new_name = data_utils.rand_name('server')
# Update the server with a new name
- resp, server = self.client.update_server(server_id,
- name=new_name)
+ self.client.update_server(server_id,
+ name=new_name)
self.client.wait_for_server_status(server_id, status)
# Verify the name of the server has changed
- resp, server = self.client.get_server(server_id)
+ server = self.client.get_server(server_id)
self.assertEqual(new_name, server['name'])
return server
@test.attr(type='gate')
+ @test.idempotent_id('5e6ccff8-349d-4852-a8b3-055df7988dd2')
def test_update_server_name(self):
# The server name should be changed to the the provided value
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
self._update_server_name(server['id'], 'ACTIVE')
@test.attr(type='gate')
+ @test.idempotent_id('6ac19cb1-27a3-40ec-b350-810bdc04c08e')
def test_update_server_name_in_stop_state(self):
# The server name should be changed to the the provided value
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
self.client.stop(server['id'])
self.client.wait_for_server_status(server['id'], 'SHUTOFF')
updated_server = self._update_server_name(server['id'], 'SHUTOFF')
self.assertNotIn('progress', updated_server)
@test.attr(type='gate')
+ @test.idempotent_id('89b90870-bc13-4b73-96af-f9d4f2b70077')
def test_update_access_server_address(self):
# The server's access addresses should reflect the provided values
- resp, server = self.create_test_server(wait_until='ACTIVE')
+ server = self.create_test_server(wait_until='ACTIVE')
# Update the IPv4 and IPv6 access addresses
- resp, body = self.client.update_server(server['id'],
- accessIPv4='1.1.1.1',
- accessIPv6='::babe:202:202')
- self.assertEqual(200, resp.status)
+ self.client.update_server(server['id'],
+ accessIPv4='1.1.1.1',
+ accessIPv6='::babe:202:202')
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the access addresses have been updated
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual('1.1.1.1', server['accessIPv4'])
self.assertEqual('::babe:202:202', server['accessIPv6'])
@test.attr(type='gate')
+ @test.idempotent_id('38fb1d02-c3c5-41de-91d3-9bc2025a75eb')
def test_create_server_with_ipv6_addr_only(self):
# Create a server without an IPv4 address(only IPv6 address).
- resp, server = self.create_test_server(accessIPv6='2001:2001::3')
- self.assertEqual('202', resp['status'])
+ server = self.create_test_server(accessIPv6='2001:2001::3')
self.client.wait_for_server_status(server['id'], 'ACTIVE')
- resp, server = self.client.get_server(server['id'])
+ server = self.client.get_server(server['id'])
self.assertEqual('2001:2001::3', server['accessIPv6'])
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index b703cfe..dd82893 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -15,13 +15,13 @@
import sys
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.api.compute import base
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -46,18 +46,20 @@
cls.client = cls.servers_client
cls.alt_os = clients.Manager(cls.isolated_creds.get_alt_creds())
cls.alt_client = cls.alt_os.servers_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('dbbfd247-c40c-449e-8f6c-d2aa7c7da7cf')
def test_server_name_blank(self):
# Create a server with name parameter empty
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
name='')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
def test_personality_file_contents_not_encoded(self):
# Use an unencoded file when creating a server with personality
@@ -65,77 +67,86 @@
person = [{'path': '/etc/testfile.txt',
'contents': file_contents}]
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
personality=person)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fcba1052-0a50-4cf3-b1ac-fae241edf02f')
def test_create_with_invalid_image(self):
# Create a server with an unknown image
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
image_id=-1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('18f5227f-d155-4429-807c-ccb103887537')
def test_create_with_invalid_flavor(self):
# Create a server with an unknown flavor
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
flavor=-1,)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7f70a4d1-608f-4794-9e56-cb182765972c')
def test_invalid_access_ip_v4_address(self):
# An access IPv4 address must match a valid address pattern
IPv4 = '1.1.1.1.1.1'
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server, accessIPv4=IPv4)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5226dd80-1e9c-4d8a-b5f9-b26ca4763fd0')
def test_invalid_ip_v6_address(self):
# An access IPv6 address must match a valid address pattern
IPv6 = 'notvalid'
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server, accessIPv6=IPv6)
+ @test.idempotent_id('7ea45b3e-e770-46fa-bfcc-9daaf6d987c0')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type=['negative', 'gate'])
def test_resize_nonexistent_server(self):
# Resize a non-existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.resize,
nonexistent_server, self.flavor_ref)
+ @test.idempotent_id('ced1a1d7-2ab6-45c9-b90f-b27d87b30efd')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type=['negative', 'gate'])
def test_resize_server_with_non_existent_flavor(self):
# Resize a server with non-existent flavor
nonexistent_flavor = data_utils.rand_uuid()
- self.assertRaises(exceptions.BadRequest, self.client.resize,
+ self.assertRaises(lib_exc.BadRequest, self.client.resize,
self.server_id, flavor_ref=nonexistent_flavor)
+ @test.idempotent_id('45436a7d-a388-4a35-a9d8-3adc5d0d940b')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize not available.')
@test.attr(type=['negative', 'gate'])
def test_resize_server_with_null_flavor(self):
# Resize a server with null flavor
- self.assertRaises(exceptions.BadRequest, self.client.resize,
+ self.assertRaises(lib_exc.BadRequest, self.client.resize,
self.server_id, flavor_ref="")
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
def test_reboot_non_existent_server(self):
# Reboot a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.reboot,
+ self.assertRaises(lib_exc.NotFound, self.client.reboot,
nonexistent_server, 'SOFT')
+ @test.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type=['negative', 'gate'])
@@ -143,281 +154,310 @@
# Pause a paused server.
self.client.pause_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'PAUSED')
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.pause_server,
self.server_id)
self.client.unpause_server(self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
def test_rebuild_reboot_deleted_server(self):
# Rebuild and Reboot a deleted server
- _, server = self.create_test_server()
+ server = self.create_test_server()
self.client.delete_server(server['id'])
self.client.wait_for_server_termination(server['id'])
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.rebuild,
server['id'], self.image_ref_alt)
- self.assertRaises(exceptions.NotFound, self.client.reboot,
+ self.assertRaises(lib_exc.NotFound, self.client.reboot,
server['id'], 'SOFT')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
def test_rebuild_non_existent_server(self):
# Rebuild a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.rebuild,
nonexistent_server,
self.image_ref_alt)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
def test_create_numeric_server_name(self):
server_name = 12345
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
name=server_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c3e0fb12-07fc-4d76-a22e-37409887afe8')
def test_create_server_name_length_exceeds_256(self):
# Create a server with name length exceeding 256 characters
server_name = 'a' * 256
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
name=server_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4e72dc2d-44c5-4336-9667-f7972e95c402')
def test_create_with_invalid_network_uuid(self):
# Pass invalid network uuid while creating a server
networks = [{'fixed_ip': '10.0.1.1', 'uuid': 'a-b-c-d-e-f-g-h-i-j'}]
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
networks=networks)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7a2efc39-530c-47de-b875-2dd01c8d39bd')
def test_create_with_non_existent_keypair(self):
# Pass a non-existent keypair while creating a server
key_name = data_utils.rand_name('key')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
key_name=key_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7fc74810-0bd2-4cd7-8244-4f33a9db865a')
def test_create_server_metadata_exceeds_length_limit(self):
# Pass really long metadata while creating a server
metadata = {'a': 'b' * 260}
- self.assertRaises((exceptions.BadRequest, exceptions.OverLimit),
+ self.assertRaises((lib_exc.BadRequest, lib_exc.OverLimit),
self.create_test_server,
meta=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
def test_update_name_of_non_existent_server(self):
# Update name of a non-existent server
server_name = data_utils.rand_name('server')
new_name = data_utils.rand_name('server') + '_updated'
- self.assertRaises(exceptions.NotFound, self.client.update_server,
+ self.assertRaises(lib_exc.NotFound, self.client.update_server,
server_name, name=new_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('38204696-17c6-44da-9590-40f87fb5a899')
def test_update_server_set_empty_name(self):
# Update name of the server to an empty string
server_name = data_utils.rand_name('server')
new_name = ''
- self.assertRaises(exceptions.BadRequest, self.client.update_server,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_server,
server_name, name=new_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('543d84c1-dd2e-4c6d-8cb2-b9da0efaa384')
def test_update_server_of_another_tenant(self):
# Update name of a server that belongs to another tenant
new_name = self.server_id + '_new'
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.update_server, self.server_id,
name=new_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5c8e244c-dada-4590-9944-749c455b431f')
def test_update_server_name_length_exceeds_256(self):
# Update name of server exceed the name length limit
new_name = 'a' * 256
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_server,
self.server_id,
name=new_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1041b4e6-514b-4855-96a5-e974b60870a3')
def test_delete_non_existent_server(self):
# Delete a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.delete_server,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_server,
nonexistent_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5c75009d-3eea-423e-bea3-61b09fd25f9c')
def test_delete_a_server_of_another_tenant(self):
# Delete a server that belongs to another tenant
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.delete_server,
self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('75f79124-277c-45e6-a373-a1d6803f4cc4')
def test_delete_server_pass_negative_id(self):
# Pass an invalid string parameter to delete server
- self.assertRaises(exceptions.NotFound, self.client.delete_server, -1)
+ self.assertRaises(lib_exc.NotFound, self.client.delete_server, -1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f4d7279b-5fd2-4bf2-9ba4-ae35df0d18c5')
def test_delete_server_pass_id_exceeding_length_limit(self):
# Pass a server ID that exceeds length limit to delete server
- self.assertRaises(exceptions.NotFound, self.client.delete_server,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_server,
sys.maxint + 1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
def test_create_with_nonexistent_security_group(self):
# Create a server with a nonexistent security group
security_groups = [{'name': 'does_not_exist'}]
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_test_server,
security_groups=security_groups)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3436b02f-1b1e-4f03-881e-c6a602327439')
def test_get_non_existent_server(self):
# Get a non existent server details
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.get_server,
+ self.assertRaises(lib_exc.NotFound, self.client.get_server,
nonexistent_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a31460a9-49e1-42aa-82ee-06e0bb7c2d03')
def test_stop_non_existent_server(self):
# Stop a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.servers_client.stop,
+ self.assertRaises(lib_exc.NotFound, self.servers_client.stop,
nonexistent_server)
+ @test.idempotent_id('6a8dc0c6-6cd4-4c0a-9f32-413881828091')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type=['negative', 'gate'])
def test_pause_non_existent_server(self):
# pause a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.pause_server,
+ self.assertRaises(lib_exc.NotFound, self.client.pause_server,
nonexistent_server)
+ @test.idempotent_id('705b8e3a-e8a7-477c-a19b-6868fc24ac75')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type=['negative', 'gate'])
def test_unpause_non_existent_server(self):
# unpause a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.unpause_server,
+ self.assertRaises(lib_exc.NotFound, self.client.unpause_server,
nonexistent_server)
+ @test.idempotent_id('c8e639a7-ece8-42dd-a2e0-49615917ba4f')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.attr(type=['negative', 'gate'])
def test_unpause_server_invalid_state(self):
# unpause an active server.
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.unpause_server,
self.server_id)
+ @test.idempotent_id('d1f032d5-7b6e-48aa-b252-d5f16dd994ca')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type=['negative', 'gate'])
def test_suspend_non_existent_server(self):
# suspend a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.suspend_server,
+ self.assertRaises(lib_exc.NotFound, self.client.suspend_server,
nonexistent_server)
+ @test.idempotent_id('7f323206-05a9-4bf8-996b-dd5b2036501b')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type=['negative', 'gate'])
def test_suspend_server_invalid_state(self):
# suspend a suspended server.
- resp, _ = self.client.suspend_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.suspend_server(self.server_id)
self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.suspend_server,
self.server_id)
self.client.resume_server(self.server_id)
+ @test.idempotent_id('221cd282-bddb-4837-a683-89c2487389b6')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type=['negative', 'gate'])
def test_resume_non_existent_server(self):
# resume a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.resume_server,
+ self.assertRaises(lib_exc.NotFound, self.client.resume_server,
nonexistent_server)
+ @test.idempotent_id('ccb6294d-c4c9-498f-8a43-554c098bfadb')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.attr(type=['negative', 'gate'])
def test_resume_server_invalid_state(self):
# resume an active server.
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.resume_server,
self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7dd919e7-413f-4198-bebb-35e2a01b13e9')
def test_get_console_output_of_non_existent_server(self):
# get the console output for a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_console_output,
nonexistent_server, 10)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
def test_force_delete_nonexistent_server_id(self):
# force-delete a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.force_delete_server,
nonexistent_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9c6d38cc-fcfb-437a-85b9-7b788af8bf01')
def test_restore_nonexistent_server_id(self):
# restore-delete a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.restore_soft_deleted_server,
nonexistent_server)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7fcadfab-bd6a-4753-8db7-4a51e51aade9')
def test_restore_server_invalid_state(self):
# we can only restore-delete a server in 'soft-delete' state
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.restore_soft_deleted_server,
self.server_id)
+ @test.idempotent_id('abca56e2-a892-48ea-b5e5-e07e69774816')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type=['negative', 'gate'])
def test_shelve_non_existent_server(self):
# shelve a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.shelve_server,
+ self.assertRaises(lib_exc.NotFound, self.client.shelve_server,
nonexistent_server)
+ @test.idempotent_id('443e4f9b-e6bf-4389-b601-3a710f15fddd')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type=['negative', 'gate'])
def test_shelve_shelved_server(self):
# shelve a shelved server.
- resp, server = self.client.shelve_server(self.server_id)
- self.assertEqual(202, resp.status)
+ self.client.shelve_server(self.server_id)
offload_time = CONF.compute.shelved_offload_time
if offload_time >= 0:
@@ -428,33 +468,35 @@
self.client.wait_for_server_status(self.server_id,
'SHELVED')
- resp, server = self.client.get_server(self.server_id)
+ server = self.client.get_server(self.server_id)
image_name = server['name'] + '-shelved'
params = {'name': image_name}
images = self.images_client.list_images(params)
self.assertEqual(1, len(images))
self.assertEqual(image_name, images[0]['name'])
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.shelve_server,
self.server_id)
self.client.unshelve_server(self.server_id)
+ @test.idempotent_id('23d23b37-afaf-40d7-aa5d-5726f82d8821')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type=['negative', 'gate'])
def test_unshelve_non_existent_server(self):
# unshelve a non existent server
nonexistent_server = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.unshelve_server,
+ self.assertRaises(lib_exc.NotFound, self.client.unshelve_server,
nonexistent_server)
+ @test.idempotent_id('8f198ded-1cca-4228-9e65-c6b449c54880')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.attr(type=['negative', 'gate'])
def test_unshelve_server_invalid_state(self):
# unshelve an active server.
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.unshelve_server,
self.server_id)
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index e07a7ed..0b2f4c6 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -26,23 +26,31 @@
class VirtualInterfacesTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
# This test needs a network and a subnet
cls.set_network_resources(network=True, subnet=True)
- super(VirtualInterfacesTestJSON, cls).resource_setup()
+ super(VirtualInterfacesTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(VirtualInterfacesTestJSON, cls).setup_clients()
cls.client = cls.servers_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
+
+ @classmethod
+ def resource_setup(cls):
+ super(VirtualInterfacesTestJSON, cls).resource_setup()
+ server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
@decorators.skip_because(bug="1183436",
condition=CONF.service_available.neutron)
@test.attr(type='gate')
+ @test.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
@test.services('network')
def test_list_virtual_interfaces(self):
# Positive test:Should be able to GET the virtual interfaces list
# for a given server_id
- resp, output = self.client.list_virtual_interfaces(self.server_id)
- self.assertEqual(200, resp.status)
+ output = self.client.list_virtual_interfaces(self.server_id)
self.assertIsNotNone(output)
virt_ifaces = output
self.assertNotEqual(0, len(virt_ifaces['virtual_interfaces']),
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index e81ccc6..e5cb744 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -15,26 +15,32 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
-from tempest import exceptions
from tempest import test
class VirtualInterfacesNegativeTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
# For this test no network resources are needed
cls.set_network_resources()
- super(VirtualInterfacesNegativeTestJSON, cls).resource_setup()
+ super(VirtualInterfacesNegativeTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(VirtualInterfacesNegativeTestJSON, cls).setup_clients()
cls.client = cls.servers_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
@test.services('network')
def test_list_virtual_interfaces_invalid_server_id(self):
# Negative test: Should not be able to GET virtual interfaces
# for an invalid server_id
invalid_server_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_virtual_interfaces,
invalid_server_id)
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index cdbaee8..2dbe123 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -15,11 +15,12 @@
import StringIO
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest import test
@@ -29,32 +30,44 @@
class AuthorizationTestJSON(base.BaseV2ComputeTest):
+
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(AuthorizationTestJSON, cls).skip_checks()
if not CONF.service_available.glance:
raise cls.skipException('Glance is not available.')
+
+ @classmethod
+ def setup_credentials(cls):
# No network resources required for this test
cls.set_network_resources()
- super(AuthorizationTestJSON, cls).resource_setup()
+ super(AuthorizationTestJSON, cls).setup_credentials()
if not cls.multi_user:
msg = "Need >1 user"
raise cls.skipException(msg)
+
+ creds = cls.isolated_creds.get_alt_creds()
+ cls.alt_manager = clients.Manager(credentials=creds)
+
+ @classmethod
+ def setup_clients(cls):
+ super(AuthorizationTestJSON, cls).setup_clients()
cls.client = cls.os.servers_client
cls.images_client = cls.os.images_client
cls.glance_client = cls.os.image_client
cls.keypairs_client = cls.os.keypairs_client
cls.security_client = cls.os.security_groups_client
- creds = cls.isolated_creds.get_alt_creds()
- cls.alt_manager = clients.Manager(credentials=creds)
-
cls.alt_client = cls.alt_manager.servers_client
cls.alt_images_client = cls.alt_manager.images_client
cls.alt_keypairs_client = cls.alt_manager.keypairs_client
cls.alt_security_client = cls.alt_manager.security_groups_client
- resp, server = cls.create_test_server(wait_until='ACTIVE')
- resp, cls.server = cls.client.get_server(server['id'])
+ @classmethod
+ def resource_setup(cls):
+ super(AuthorizationTestJSON, cls).resource_setup()
+ server = cls.create_test_server(wait_until='ACTIVE')
+ cls.server = cls.client.get_server(server['id'])
name = data_utils.rand_name('image')
body = cls.glance_client.create_image(name=name,
@@ -91,85 +104,98 @@
super(AuthorizationTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('56816e4a-bd34-47b5-aee9-268c3efeb5d4')
def test_get_server_for_alt_account_fails(self):
# A GET request for a server on another user's account should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.get_server,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.get_server,
self.server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('fb8a4870-6d9d-44ad-8375-95d52e98d9f6')
def test_delete_server_for_alt_account_fails(self):
# A DELETE request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.delete_server,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.delete_server,
self.server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('d792f91f-1d49-4eb5-b1ff-b229c4b9dc64')
def test_update_server_for_alt_account_fails(self):
# An update server request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.update_server,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.update_server,
self.server['id'], name='test')
@test.attr(type='gate')
+ @test.idempotent_id('488f24df-d7f7-4207-949a-f17fcb8e8769')
def test_list_server_addresses_for_alt_account_fails(self):
# A list addresses request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.list_addresses,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.list_addresses,
self.server['id'])
@test.attr(type='gate')
+ @test.idempotent_id('00b442d0-2e72-40e7-9b1f-31772e36da01')
def test_list_server_addresses_by_network_for_alt_account_fails(self):
# A list address/network request for another user's server should fail
server_id = self.server['id']
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.list_addresses_by_network, server_id,
'public')
@test.attr(type='gate')
+ @test.idempotent_id('cc90b35a-19f0-45d2-b680-2aabf934aa22')
def test_list_servers_with_alternate_tenant(self):
# A list on servers from one tenant should not
# show on alternate tenant
# Listing servers from alternate tenant
alt_server_ids = []
- resp, body = self.alt_client.list_servers()
+ body = self.alt_client.list_servers()
alt_server_ids = [s['id'] for s in body['servers']]
self.assertNotIn(self.server['id'], alt_server_ids)
@test.attr(type='gate')
+ @test.idempotent_id('376dbc16-0779-4384-a723-752774799641')
def test_change_password_for_alt_account_fails(self):
# A change password request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.change_password,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.change_password,
self.server['id'], 'newpass')
@test.attr(type='gate')
+ @test.idempotent_id('14cb5ff5-f646-45ca-8f51-09081d6c0c24')
def test_reboot_server_for_alt_account_fails(self):
# A reboot request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.reboot,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.reboot,
self.server['id'], 'HARD')
@test.attr(type='gate')
+ @test.idempotent_id('8a0bce51-cd00-480b-88ba-dbc7d8408a37')
def test_rebuild_server_for_alt_account_fails(self):
# A rebuild request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.rebuild,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.rebuild,
self.server['id'], self.image_ref_alt)
@test.attr(type='gate')
+ @test.idempotent_id('e4da647e-f982-4e61-9dad-1d1abebfb933')
def test_resize_server_for_alt_account_fails(self):
# A resize request for another user's server should fail
- self.assertRaises(exceptions.NotFound, self.alt_client.resize,
+ self.assertRaises(lib_exc.NotFound, self.alt_client.resize,
self.server['id'], self.flavor_ref_alt)
@test.attr(type='gate')
+ @test.idempotent_id('a9fe8112-0ffa-4902-b061-f892bd5fe0d3')
def test_create_image_for_alt_account_fails(self):
# A create image request for another user's server should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.create_image,
self.server['id'], 'testImage')
@test.attr(type='gate')
+ @test.idempotent_id('95d445f6-babc-4f2e-aea3-aa24ec5e7f0d')
def test_create_server_with_unauthorized_image(self):
# Server creation with another user's image should fail
- self.assertRaises(exceptions.BadRequest, self.alt_client.create_server,
+ self.assertRaises(lib_exc.BadRequest, self.alt_client.create_server,
'test', self.image['id'], self.flavor_ref)
@test.attr(type='gate')
+ @test.idempotent_id('acf8724b-142b-4044-82c3-78d31a533f24')
def test_create_server_fails_when_tenant_incorrect(self):
# A create server request should fail if the tenant id does not match
# the current user
@@ -178,11 +204,12 @@
request_part='url',
auth_data=self.client.auth_provider.auth_data
)
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.alt_client.create_server, 'test',
self.image['id'], self.flavor_ref)
@test.attr(type='gate')
+ @test.idempotent_id('f03d1ded-7fd4-4d29-bc13-e2391f29c625')
def test_create_keypair_in_analt_user_tenant(self):
# A create keypair request should fail if the tenant id does not match
# the current user
@@ -196,7 +223,7 @@
)
resp = {}
resp['status'] = None
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.alt_keypairs_client.create_keypair, k_name)
finally:
# Next request the base_url is back to normal
@@ -206,33 +233,38 @@
"if the tenant id does not match the current user")
@test.attr(type='gate')
+ @test.idempotent_id('85bcdd8f-56b4-4868-ae56-63fbf6f7e405')
def test_get_keypair_of_alt_account_fails(self):
# A GET request for another user's keypair should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_keypairs_client.get_keypair,
self.keypairname)
@test.attr(type='gate')
+ @test.idempotent_id('6d841683-a8e0-43da-a1b8-b339f7692b61')
def test_delete_keypair_of_alt_account_fails(self):
# A DELETE request for another user's keypair should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_keypairs_client.delete_keypair,
self.keypairname)
@test.attr(type='gate')
+ @test.idempotent_id('fcb2e144-36e3-4dfb-9f9f-e72fcdec5656')
def test_get_image_for_alt_account_fails(self):
# A GET request for an image on another user's account should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.get_image, self.image['id'])
@test.attr(type='gate')
+ @test.idempotent_id('9facb962-f043-4a9d-b9ee-166a32dea098')
def test_delete_image_for_alt_account_fails(self):
# A DELETE request for another user's image should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.delete_image,
self.image['id'])
@test.attr(type='gate')
+ @test.idempotent_id('752c917e-83be-499d-a422-3559127f7d3c')
def test_create_security_group_in_analt_user_tenant(self):
# A create security group request should fail if the tenant id does not
# match the current user
@@ -247,7 +279,7 @@
)
resp = {}
resp['status'] = None
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.alt_security_client.create_security_group,
s_name, s_description)
finally:
@@ -258,20 +290,23 @@
"the tenant id does not match the current user")
@test.attr(type='gate')
+ @test.idempotent_id('9db3590f-4d15-4e5f-985e-b28514919a6f')
def test_get_security_group_of_alt_account_fails(self):
# A GET request for another user's security group should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_security_client.get_security_group,
self.security_group['id'])
@test.attr(type='gate')
+ @test.idempotent_id('155387a5-2bbc-4acf-ab06-698dae537ea5')
def test_delete_security_group_of_alt_account_fails(self):
# A DELETE request for another user's security group should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_security_client.delete_security_group,
self.security_group['id'])
@test.attr(type='gate')
+ @test.idempotent_id('b2b76de0-210a-4089-b921-591c9ec552f6')
def test_create_security_group_rule_in_analt_user_tenant(self):
# A create security group rule request should fail if the tenant id
# does not match the current user
@@ -288,7 +323,7 @@
)
resp = {}
resp['status'] = None
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.alt_security_client.
create_security_group_rule,
parent_group_id, ip_protocol, from_port,
@@ -302,42 +337,47 @@
" current user")
@test.attr(type='gate')
+ @test.idempotent_id('c6044177-37ef-4ce4-b12c-270ddf26d7da')
def test_delete_security_group_rule_of_alt_account_fails(self):
# A DELETE request for another user's security group rule
# should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_security_client.delete_security_group_rule,
self.rule['id'])
@test.attr(type='gate')
+ @test.idempotent_id('c5f52351-53d9-4fc9-83e5-917f7f5e3d71')
def test_set_metadata_of_alt_account_server_fails(self):
# A set metadata for another user's server should fail
req_metadata = {'meta1': 'data1', 'meta2': 'data2'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.set_server_metadata,
self.server['id'],
req_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('fb6f51e9-df15-4939-898d-1aca38c258f0')
def test_set_metadata_of_alt_account_image_fails(self):
# A set metadata for another user's image should fail
req_metadata = {'meta1': 'value1', 'meta2': 'value2'}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.set_image_metadata,
self.image['id'], req_metadata)
@test.attr(type='gate')
+ @test.idempotent_id('dea1936a-473d-49f2-92ad-97bb7aded22e')
def test_get_metadata_of_alt_account_server_fails(self):
# A get metadata for another user's server should fail
req_metadata = {'meta1': 'data1'}
self.client.set_server_metadata(self.server['id'], req_metadata)
self.addCleanup(self.client.delete_server_metadata_item,
self.server['id'], 'meta1')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.get_server_metadata_item,
self.server['id'], 'meta1')
@test.attr(type='gate')
+ @test.idempotent_id('16b2d724-0d3b-4216-a9fa-97bd4d9cf670')
def test_get_metadata_of_alt_account_image_fails(self):
# A get metadata for another user's image should fail
req_metadata = {'meta1': 'value1'}
@@ -345,22 +385,24 @@
self.image['id'], 'meta1')
self.images_client.set_image_metadata(self.image['id'],
req_metadata)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.get_image_metadata_item,
self.image['id'], 'meta1')
@test.attr(type='gate')
+ @test.idempotent_id('79531e2e-e721-493c-8b30-a35db36fdaa6')
def test_delete_metadata_of_alt_account_server_fails(self):
# A delete metadata for another user's server should fail
req_metadata = {'meta1': 'data1'}
self.addCleanup(self.client.delete_server_metadata_item,
self.server['id'], 'meta1')
self.client.set_server_metadata(self.server['id'], req_metadata)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.delete_server_metadata_item,
self.server['id'], 'meta1')
@test.attr(type='gate')
+ @test.idempotent_id('a5175dcf-cef8-43d6-9b77-3cb707d62e94')
def test_delete_metadata_of_alt_account_image_fails(self):
# A delete metadata for another user's image should fail
req_metadata = {'meta1': 'data1'}
@@ -368,13 +410,14 @@
self.image['id'], 'meta1')
self.images_client.set_image_metadata(self.image['id'],
req_metadata)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_images_client.delete_image_metadata_item,
self.image['id'], 'meta1')
@test.attr(type='gate')
+ @test.idempotent_id('b0c1e7a0-8853-40fd-8384-01f93d116cae')
def test_get_console_output_of_alt_account_server_fails(self):
# A Get Console Output for another user's server should fail
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_client.get_console_output,
self.server['id'], 10)
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index 46e7251..1063f90 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -28,12 +28,12 @@
class ExtensionsTestJSON(base.BaseV2ComputeTest):
@test.attr(type='gate')
+ @test.idempotent_id('3bb27738-b759-4e0d-a5fa-37d7a6df07d1')
def test_list_extensions(self):
# List of all extensions
if len(CONF.compute_feature_enabled.api_extensions) == 0:
raise self.skipException('There are not any extensions configured')
- resp, extensions = self.extensions_client.list_extensions()
- self.assertEqual(200, resp.status)
+ extensions = self.extensions_client.list_extensions()
ext = CONF.compute_feature_enabled.api_extensions[0]
if ext == 'all':
self.assertIn('Hosts', map(lambda x: x['name'], extensions))
@@ -45,10 +45,10 @@
extension_list = map(lambda x: x['alias'], extensions)
LOG.debug("Nova extensions: %s" % ','.join(extension_list))
+ @test.idempotent_id('05762f39-bdfa-4cdb-9b46-b78f8e78e2fd')
@test.requires_ext(extension='os-consoles', service='compute')
@test.attr(type='gate')
def test_get_extension(self):
# get the specified extensions
- resp, extension = self.extensions_client.get_extension('os-consoles')
- self.assertEqual(200, resp.status)
+ extension = self.extensions_client.get_extension('os-consoles')
self.assertEqual('os-consoles', extension['alias'])
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index eb71d6d..a933f81 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -44,14 +44,14 @@
]
def _get_server_details(self, server_id):
- _resp, body = self.admin_servers_client.get_server(server_id)
+ body = self.admin_servers_client.get_server(server_id)
return body
def _get_host_for_server(self, server_id):
return self._get_server_details(server_id)[self._host_key]
def _migrate_server_to(self, server_id, dest_host):
- _resp, body = self.admin_servers_client.live_migrate_server(
+ body = self.admin_servers_client.live_migrate_server(
server_id, dest_host,
CONF.compute_feature_enabled.block_migration_for_live_migration)
return body
@@ -69,10 +69,8 @@
if 'ACTIVE' == self._get_server_status(server_id):
return server_id
else:
- _, server = self.create_test_server(wait_until="ACTIVE")
+ server = self.create_test_server(wait_until="ACTIVE")
server_id = server['id']
- self.password = server['adminPass']
- self.password = 'password'
self.created_server_ids.append(server_id)
return server_id
@@ -83,6 +81,7 @@
self.volumes_client.wait_for_volume_status(volume_id, 'available')
self.volumes_client.delete_volume(volume_id)
+ @test.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
'Live migration not available')
@test.attr(type='gate')
@@ -98,6 +97,7 @@
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
self.assertEqual(target_host, self._get_host_for_server(server_id))
+ @test.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration or not
CONF.compute_feature_enabled.
block_migration_for_live_migration,
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index 281b2b3..bed53d6 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -35,19 +35,20 @@
cls.admin_servers_client = cls.os_adm.servers_client
def _migrate_server_to(self, server_id, dest_host):
- _resp, body = self.admin_servers_client.live_migrate_server(
+ body = self.admin_servers_client.live_migrate_server(
server_id, dest_host,
CONF.compute_feature_enabled.
block_migration_for_live_migration)
return body
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7fb7856e-ae92-44c9-861a-af62d7830bcb')
def test_invalid_host_for_migration(self):
# Migrating to an invalid host should not change the status
target_host = data_utils.rand_name('host-')
- _, server = self.create_test_server(wait_until="ACTIVE")
+ server = self.create_test_server(wait_until="ACTIVE")
server_id = server['id']
- self.assertRaises(exceptions.BadRequest, self._migrate_server_to,
+ self.assertRaises(lib_exc.BadRequest, self._migrate_server_to,
server_id, target_host)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
diff --git a/tempest/api/compute/test_networks.py b/tempest/api/compute/test_networks.py
index 86779b3..c30beb7 100644
--- a/tempest/api/compute/test_networks.py
+++ b/tempest/api/compute/test_networks.py
@@ -28,6 +28,7 @@
cls.client = cls.os.networks_client
@test.attr(type='gate')
+ @test.idempotent_id('3fe07175-312e-49a5-a623-5f52eeada4c2')
def test_list_networks(self):
- _, networks = self.client.list_networks()
+ networks = self.client.list_networks()
self.assertNotEmpty(networks, "No networks found.")
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index db2e281..1df67d9 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -40,6 +40,7 @@
'cores', 'security_groups'))
@test.attr(type='smoke')
+ @test.idempotent_id('f1ef0a97-dbbb-4cca-adc5-c9fbc4f76107')
def test_get_quotas(self):
# User can get the quota set for it's tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -56,6 +57,7 @@
self.assertIn(quota, quota_set.keys())
@test.attr(type='smoke')
+ @test.idempotent_id('9bfecac7-b966-4f47-913f-1a9e2c12134a')
def test_get_default_quotas(self):
# User can get the default quota set for it's tenant
expected_quota_set = self.default_quota_set | set(['id'])
@@ -65,6 +67,7 @@
self.assertIn(quota, quota_set.keys())
@test.attr(type='smoke')
+ @test.idempotent_id('cd65d997-f7e4-4966-a7e9-d5001b674fdc')
def test_compare_tenant_quotas_with_default_quotas(self):
# Tenants are created with the default quota values
defualt_quota_set = \
diff --git a/tempest/api/compute/test_tenant_networks.py b/tempest/api/compute/test_tenant_networks.py
index 0591acc..3a712dd 100644
--- a/tempest/api/compute/test_tenant_networks.py
+++ b/tempest/api/compute/test_tenant_networks.py
@@ -24,6 +24,7 @@
cls.client = cls.os.tenant_networks_client
@test.attr(type='gate')
+ @test.idempotent_id('edfea98e-bbe3-4c7a-9739-87b986baff26')
def test_list_show_tenant_networks(self):
tenant_networks = self.client.list_tenant_networks()
self.assertNotEmpty(tenant_networks, "No tenant networks found.")
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 7fef52f..43d2302 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -30,14 +30,22 @@
self.attachment = None
@classmethod
- def resource_setup(cls):
- cls.prepare_instance_network()
- super(AttachVolumeTestJSON, cls).resource_setup()
- cls.device = CONF.compute.volume_device_name
+ def skip_checks(cls):
+ super(AttachVolumeTestJSON, 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_credentials(cls):
+ cls.prepare_instance_network()
+ super(AttachVolumeTestJSON, cls).setup_credentials()
+
+ @classmethod
+ def resource_setup(cls):
+ super(AttachVolumeTestJSON, cls).resource_setup()
+ cls.device = CONF.compute.volume_device_name
+
def _detach(self, server_id, volume_id):
if self.attachment:
self.servers_client.detach_volume(server_id, volume_id)
@@ -53,11 +61,11 @@
def _create_and_attach(self):
# Start a server and wait for it to become ready
admin_pass = self.image_ssh_password
- _, self.server = self.create_test_server(wait_until='ACTIVE',
- adminPass=admin_pass)
+ self.server = self.create_test_server(wait_until='ACTIVE',
+ adminPass=admin_pass)
# Record addresses so that we can ssh later
- _, self.server['addresses'] = (
+ self.server['addresses'] = (
self.servers_client.list_addresses(self.server['id']))
# Create a volume and wait for it to become ready
@@ -68,7 +76,7 @@
'available')
# Attach the volume to the server
- _, self.attachment = self.servers_client.attach_volume(
+ self.attachment = self.servers_client.attach_volume(
self.server['id'],
self.volume['id'],
device='/dev/%s' % self.device)
@@ -76,6 +84,7 @@
self.addCleanup(self._detach, self.server['id'], self.volume['id'])
+ @test.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
@testtools.skipUnless(CONF.compute.run_ssh, 'SSH required for this test')
@test.attr(type='gate')
def test_attach_detach_volume(self):
@@ -112,17 +121,18 @@
self.assertNotIn(self.device, partitions)
@test.attr(type='gate')
+ @test.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
def test_list_get_volume_attachments(self):
# Create Server, Volume and attach that Volume to Server
self._create_and_attach()
# List Volume attachment of the server
- _, body = self.servers_client.list_volume_attachments(
+ body = self.servers_client.list_volume_attachments(
self.server['id'])
self.assertEqual(1, len(body))
self.assertIn(self.attachment, body)
# Get Volume attachment of the server
- _, body = self.servers_client.get_volume_attachment(
+ body = self.servers_client.get_volume_attachment(
self.server['id'],
self.attachment['id'])
self.assertEqual(self.server['id'], body['serverId'])
diff --git a/tempest/api/compute/volumes/test_volumes_get.py b/tempest/api/compute/volumes/test_volumes_get.py
index d441427..207476d 100644
--- a/tempest/api/compute/volumes/test_volumes_get.py
+++ b/tempest/api/compute/volumes/test_volumes_get.py
@@ -27,25 +27,29 @@
class VolumesGetTestJSON(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesGetTestJSON, cls).resource_setup()
- cls.client = cls.volumes_extensions_client
+ def skip_checks(cls):
+ super(VolumesGetTestJSON, 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(VolumesGetTestJSON, cls).setup_clients()
+ cls.client = cls.volumes_extensions_client
+
@test.attr(type='smoke')
+ @test.idempotent_id('f10f25eb-9775-4d9d-9cbe-1cf54dae9d5f')
def test_volume_create_get_delete(self):
# CREATE, GET, DELETE Volume
volume = None
- v_name = data_utils.rand_name('Volume-%s-') % self._interface
+ v_name = data_utils.rand_name('Volume')
metadata = {'Type': 'work'}
# Create volume
- resp, volume = self.client.create_volume(size=1,
- display_name=v_name,
- metadata=metadata)
+ volume = self.client.create_volume(size=1,
+ display_name=v_name,
+ metadata=metadata)
self.addCleanup(self.delete_volume, volume['id'])
- self.assertEqual(200, resp.status)
self.assertIn('id', volume)
self.assertIn('displayName', volume)
self.assertEqual(volume['displayName'], v_name,
@@ -56,8 +60,7 @@
# Wait for Volume status to become ACTIVE
self.client.wait_for_volume_status(volume['id'], 'available')
# GET Volume
- resp, fetched_volume = self.client.get_volume(volume['id'])
- self.assertEqual(200, resp.status)
+ fetched_volume = self.client.get_volume(volume['id'])
# Verification of details of fetched Volume
self.assertEqual(v_name,
fetched_volume['displayName'],
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index 6bf9519..501e9ed 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -32,24 +32,32 @@
"""
@classmethod
- def resource_setup(cls):
- super(VolumesTestJSON, cls).resource_setup()
- cls.client = cls.volumes_extensions_client
+ def skip_checks(cls):
+ super(VolumesTestJSON, 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(VolumesTestJSON, cls).setup_clients()
+ cls.client = cls.volumes_extensions_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(VolumesTestJSON, cls).resource_setup()
# Create 3 Volumes
cls.volume_list = []
cls.volume_id_list = []
for i in range(3):
- v_name = data_utils.rand_name('volume-%s' % cls._interface)
+ v_name = data_utils.rand_name('volume')
metadata = {'Type': 'work'}
try:
- resp, volume = cls.client.create_volume(size=1,
- display_name=v_name,
- metadata=metadata)
+ volume = cls.client.create_volume(size=1,
+ display_name=v_name,
+ metadata=metadata)
cls.client.wait_for_volume_status(volume['id'], 'available')
- resp, volume = cls.client.get_volume(volume['id'])
+ volume = cls.client.get_volume(volume['id'])
cls.volume_list.append(volume)
cls.volume_id_list.append(volume['id'])
except Exception:
@@ -76,11 +84,11 @@
super(VolumesTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('bc2dd1a0-15af-48e5-9990-f2e75a48325d')
def test_volume_list(self):
# Should return the list of Volumes
# Fetch all Volumes
- resp, fetched_list = self.client.list_volumes()
- self.assertEqual(200, resp.status)
+ fetched_list = self.client.list_volumes()
# Now check if all the Volumes created in setup are in fetched list
missing_volumes = [
v for v in self.volume_list if v not in fetched_list
@@ -92,11 +100,11 @@
for m_vol in missing_volumes))
@test.attr(type='gate')
+ @test.idempotent_id('bad0567a-5a4f-420b-851e-780b55bb867c')
def test_volume_list_with_details(self):
# Should return the list of Volumes with details
# Fetch all Volumes
- resp, fetched_list = self.client.list_volumes_with_detail()
- self.assertEqual(200, resp.status)
+ fetched_list = self.client.list_volumes_with_detail()
# Now check if all the Volumes created in setup are in fetched list
missing_volumes = [
v for v in self.volume_list if v not in fetched_list
@@ -108,34 +116,33 @@
for m_vol in missing_volumes))
@test.attr(type='gate')
+ @test.idempotent_id('1048ed81-2baf-487a-b284-c0622b86e7b8')
def test_volume_list_param_limit(self):
# Return the list of volumes based on limit set
params = {'limit': 2}
- resp, fetched_vol_list = self.client.list_volumes(params=params)
- self.assertEqual(200, resp.status)
+ fetched_vol_list = self.client.list_volumes(params=params)
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volumes by limit set")
@test.attr(type='gate')
+ @test.idempotent_id('33985568-4965-49d5-9bcc-0aa007ca5b7a')
def test_volume_list_with_detail_param_limit(self):
# Return the list of volumes with details based on limit set.
params = {'limit': 2}
- resp, fetched_vol_list = \
- self.client.list_volumes_with_detail(params=params)
- self.assertEqual(200, resp.status)
+ fetched_vol_list = self.client.list_volumes_with_detail(params=params)
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volume details by limit set")
@test.attr(type='gate')
+ @test.idempotent_id('51c22651-a074-4ea7-af0b-094f9331303e')
def test_volume_list_param_offset_and_limit(self):
# Return the list of volumes based on offset and limit set.
# get all volumes list
- response, all_vol_list = self.client.list_volumes()
+ all_vol_list = self.client.list_volumes()
params = {'offset': 1, 'limit': 1}
- resp, fetched_vol_list = self.client.list_volumes(params=params)
- self.assertEqual(200, resp.status)
+ fetched_vol_list = self.client.list_volumes(params=params)
# Validating length of the fetched volumes
self.assertEqual(len(fetched_vol_list), params['limit'],
@@ -147,14 +154,13 @@
"Failed to list volumes by offset and limit")
@test.attr(type='gate')
+ @test.idempotent_id('06b6abc4-3f10-48e9-a7a1-3facc98f03e5')
def test_volume_list_with_detail_param_offset_and_limit(self):
# Return the list of volumes details based on offset and limit set.
# get all volumes list
- response, all_vol_list = self.client.list_volumes_with_detail()
+ all_vol_list = self.client.list_volumes_with_detail()
params = {'offset': 1, 'limit': 1}
- resp, fetched_vol_list = \
- self.client.list_volumes_with_detail(params=params)
- self.assertEqual(200, resp.status)
+ fetched_vol_list = self.client.list_volumes_with_detail(params=params)
# Validating length of the fetched volumes
self.assertEqual(len(fetched_vol_list), params['limit'],
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index f0f9879..89f6817 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -15,10 +15,11 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -27,74 +28,87 @@
class VolumesNegativeTest(base.BaseV2ComputeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesNegativeTest, cls).resource_setup()
- cls.client = cls.volumes_extensions_client
+ def skip_checks(cls):
+ super(VolumesNegativeTest, 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(VolumesNegativeTest, cls).setup_clients()
+ cls.client = cls.volumes_extensions_client
+
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c03ea686-905b-41a2-8748-9635154b7c57')
def test_volume_get_nonexistent_volume_id(self):
# Negative: Should not be able to get details of nonexistent volume
# Creating a nonexistent volume id
# Trying to GET a non existent volume
- self.assertRaises(exceptions.NotFound, self.client.get_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.get_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('54a34226-d910-4b00-9ef8-8683e6c55846')
def test_volume_delete_nonexistent_volume_id(self):
# Negative: Should not be able to delete nonexistent Volume
# Creating nonexistent volume id
# Trying to DELETE a non existent volume
- self.assertRaises(exceptions.NotFound, self.client.delete_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5125ae14-152b-40a7-b3c5-eae15e9022ef')
def test_create_volume_with_invalid_size(self):
# Negative: Should not be able to create volume with invalid size
# in request
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='#$%', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
def test_create_volume_with_out_passing_size(self):
# Negative: Should not be able to create volume without passing size
# in request
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8cce995e-0a83-479a-b94d-e1e40b8a09d1')
def test_create_volume_with_size_zero(self):
# Negative: Should not be able to create volume with size zero
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='0', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f01904f2-e975-4915-98ce-cb5fa27bde4f')
def test_get_invalid_volume_id(self):
# Negative: Should not be able to get volume with invalid id
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_volume, '#$%%&^&^')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('62bab09a-4c03-4617-8cca-8572bc94af9b')
def test_get_volume_without_passing_volume_id(self):
# Negative: Should not be able to get volume when empty ID is passed
- self.assertRaises(exceptions.NotFound, self.client.get_volume, '')
+ self.assertRaises(lib_exc.NotFound, self.client.get_volume, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('62972737-124b-4513-b6cf-2f019f178494')
def test_delete_invalid_volume_id(self):
# Negative: Should not be able to delete volume when invalid ID is
# passed
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_volume, '!@#$%^&*()')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0d1417c5-4ae8-4c2c-adc5-5f0b864253e5')
def test_delete_volume_without_passing_volume_id(self):
# Negative: Should not be able to delete volume when empty ID is passed
- self.assertRaises(exceptions.NotFound, self.client.delete_volume, '')
+ self.assertRaises(lib_exc.NotFound, self.client.delete_volume, '')
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index 2ec1017..5992921 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest import config
-from tempest import exceptions
import tempest.test
@@ -21,16 +22,26 @@
class BaseDataProcessingTest(tempest.test.BaseTestCase):
- _interface = 'json'
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseDataProcessingTest, cls).skip_checks()
+ if not CONF.service_available.sahara:
+ raise cls.skipException('Sahara support is required')
+
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseDataProcessingTest, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseDataProcessingTest, cls).setup_clients()
+ cls.client = cls.os.data_processing_client
@classmethod
def resource_setup(cls):
super(BaseDataProcessingTest, cls).resource_setup()
- if not CONF.service_available.sahara:
- raise cls.skipException('Sahara support is required')
-
- cls.os = cls.get_client_manager()
- cls.client = cls.os.data_processing_client
cls.flavor_ref = CONF.compute.flavor_ref
@@ -63,7 +74,7 @@
for resource_id in resource_id_list:
try:
method(resource_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# ignore errors while auto removing created resource
pass
@@ -77,12 +88,12 @@
object. All resources created in this method will be automatically
removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_node_group_template(name, plugin_name,
- hadoop_version,
- node_processes,
- flavor_id,
- node_configs,
- **kwargs)
+ resp_body = cls.client.create_node_group_template(name, plugin_name,
+ hadoop_version,
+ node_processes,
+ flavor_id,
+ node_configs,
+ **kwargs)
# store id of created node group template
cls._node_group_templates.append(resp_body['id'])
@@ -97,11 +108,11 @@
object. All resources created in this method will be automatically
removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_cluster_template(name, plugin_name,
- hadoop_version,
- node_groups,
- cluster_configs,
- **kwargs)
+ resp_body = cls.client.create_cluster_template(name, plugin_name,
+ hadoop_version,
+ node_groups,
+ cluster_configs,
+ **kwargs)
# store id of created cluster template
cls._cluster_templates.append(resp_body['id'])
@@ -115,7 +126,7 @@
object. All resources created in this method will be automatically
removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_data_source(name, type, url, **kwargs)
+ resp_body = cls.client.create_data_source(name, type, url, **kwargs)
# store id of created data source
cls._data_sources.append(resp_body['id'])
@@ -128,7 +139,7 @@
It returns created object. All resources created in this method will
be automatically removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_job_binary_internal(name, data)
+ resp_body = cls.client.create_job_binary_internal(name, data)
# store id of created job binary internal
cls._job_binary_internals.append(resp_body['id'])
@@ -142,7 +153,7 @@
object. All resources created in this method will be automatically
removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_job_binary(name, url, extra, **kwargs)
+ resp_body = cls.client.create_job_binary(name, url, extra, **kwargs)
# store id of created job binary
cls._job_binaries.append(resp_body['id'])
@@ -156,8 +167,8 @@
object. All resources created in this method will be automatically
removed in tearDownClass method.
"""
- _, resp_body = cls.client.create_job(name,
- job_type, mains, libs, **kwargs)
+ resp_body = cls.client.create_job(name,
+ job_type, mains, libs, **kwargs)
# store id of created job
cls._jobs.append(resp_body['id'])
diff --git a/tempest/api/data_processing/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
index 537f90c..af7cbaf 100644
--- a/tempest/api/data_processing/test_cluster_templates.py
+++ b/tempest/api/data_processing/test_cluster_templates.py
@@ -112,29 +112,33 @@
return resp_body['id'], template_name
@test.attr(type='smoke')
+ @test.idempotent_id('3525f1f1-3f9c-407d-891a-a996237e728b')
def test_cluster_template_create(self):
self._create_cluster_template()
@test.attr(type='smoke')
+ @test.idempotent_id('7a161882-e430-4840-a1c6-1d928201fab2')
def test_cluster_template_list(self):
template_info = self._create_cluster_template()
# check for cluster template in list
- _, templates = self.client.list_cluster_templates()
+ templates = self.client.list_cluster_templates()
templates_info = [(template['id'], template['name'])
for template in templates]
self.assertIn(template_info, templates_info)
@test.attr(type='smoke')
+ @test.idempotent_id('2b75fe22-f731-4b0f-84f1-89ab25f86637')
def test_cluster_template_get(self):
template_id, template_name = self._create_cluster_template()
# check cluster template fetch by id
- _, template = self.client.get_cluster_template(template_id)
+ template = self.client.get_cluster_template(template_id)
self.assertEqual(template_name, template['name'])
self.assertDictContainsSubset(self.cluster_template, template)
@test.attr(type='smoke')
+ @test.idempotent_id('ff1fd989-171c-4dd7-91fd-9fbc71b09675')
def test_cluster_template_delete(self):
template_id, _ = self._create_cluster_template()
diff --git a/tempest/api/data_processing/test_data_sources.py b/tempest/api/data_processing/test_data_sources.py
index 3650751..dd16b2f 100644
--- a/tempest/api/data_processing/test_data_sources.py
+++ b/tempest/api/data_processing/test_data_sources.py
@@ -68,33 +68,37 @@
def _list_data_sources(self, source_info):
# check for data source in list
- _, sources = self.client.list_data_sources()
+ sources = self.client.list_data_sources()
sources_info = [(source['id'], source['name']) for source in sources]
self.assertIn(source_info, sources_info)
def _get_data_source(self, source_id, source_name, source_body):
# check data source fetch by id
- _, source = self.client.get_data_source(source_id)
+ source = self.client.get_data_source(source_id)
self.assertEqual(source_name, source['name'])
self.assertDictContainsSubset(source_body, source)
@test.attr(type='smoke')
+ @test.idempotent_id('9e0e836d-c372-4fca-91b7-b66c3e9646c8')
def test_swift_data_source_create(self):
self._create_data_source(self.swift_data_source_with_creds)
@test.attr(type='smoke')
+ @test.idempotent_id('3cb87a4a-0534-4b97-9edc-8bbc822b68a0')
def test_swift_data_source_list(self):
source_info = (
self._create_data_source(self.swift_data_source_with_creds))
self._list_data_sources(source_info)
@test.attr(type='smoke')
+ @test.idempotent_id('fc07409b-6477-4cb3-9168-e633c46b227f')
def test_swift_data_source_get(self):
source_id, source_name = (
self._create_data_source(self.swift_data_source_with_creds))
self._get_data_source(source_id, source_name, self.swift_data_source)
@test.attr(type='smoke')
+ @test.idempotent_id('df53669c-0cd1-4cf7-b408-4cf215d8beb8')
def test_swift_data_source_delete(self):
source_id, _ = (
self._create_data_source(self.swift_data_source_with_creds))
@@ -103,15 +107,18 @@
self.client.delete_data_source(source_id)
@test.attr(type='smoke')
+ @test.idempotent_id('88505d52-db01-4229-8f1d-a1137da5fe2d')
def test_local_hdfs_data_source_create(self):
self._create_data_source(self.local_hdfs_data_source)
@test.attr(type='smoke')
+ @test.idempotent_id('81d7d42a-d7f6-4d9b-b38c-0801a4dfe3c2')
def test_local_hdfs_data_source_list(self):
source_info = self._create_data_source(self.local_hdfs_data_source)
self._list_data_sources(source_info)
@test.attr(type='smoke')
+ @test.idempotent_id('ec0144c6-db1e-4169-bb06-7abae14a8443')
def test_local_hdfs_data_source_get(self):
source_id, source_name = (
self._create_data_source(self.local_hdfs_data_source))
@@ -119,6 +126,7 @@
source_id, source_name, self.local_hdfs_data_source)
@test.attr(type='smoke')
+ @test.idempotent_id('e398308b-4230-4f86-ba10-9b0b60a59c8d')
def test_local_hdfs_data_source_delete(self):
source_id, _ = self._create_data_source(self.local_hdfs_data_source)
@@ -126,15 +134,18 @@
self.client.delete_data_source(source_id)
@test.attr(type='smoke')
+ @test.idempotent_id('bfd91128-e642-4d95-a973-3e536962180c')
def test_external_hdfs_data_source_create(self):
self._create_data_source(self.external_hdfs_data_source)
@test.attr(type='smoke')
+ @test.idempotent_id('92e2be72-f7ab-499d-ae01-fb9943c90d8e')
def test_external_hdfs_data_source_list(self):
source_info = self._create_data_source(self.external_hdfs_data_source)
self._list_data_sources(source_info)
@test.attr(type='smoke')
+ @test.idempotent_id('a31edb1b-6bc6-4f42-871f-70cd243184ac')
def test_external_hdfs_data_source_get(self):
source_id, source_name = (
self._create_data_source(self.external_hdfs_data_source))
@@ -142,6 +153,7 @@
source_id, source_name, self.external_hdfs_data_source)
@test.attr(type='smoke')
+ @test.idempotent_id('295924cd-a085-4b45-aea8-0707cdb2da7e')
def test_external_hdfs_data_source_delete(self):
source_id, _ = self._create_data_source(self.external_hdfs_data_source)
diff --git a/tempest/api/data_processing/test_job_binaries.py b/tempest/api/data_processing/test_job_binaries.py
index d006991..fb21270 100644
--- a/tempest/api/data_processing/test_job_binaries.py
+++ b/tempest/api/data_processing/test_job_binaries.py
@@ -70,29 +70,33 @@
return resp_body['id'], binary_name
@test.attr(type='smoke')
+ @test.idempotent_id('c00d43f8-4360-45f8-b280-af1a201b12d3')
def test_swift_job_binary_create(self):
self._create_job_binary(self.swift_job_binary_with_extra)
@test.attr(type='smoke')
+ @test.idempotent_id('f8809352-e79d-4748-9359-ce1efce89f2a')
def test_swift_job_binary_list(self):
binary_info = self._create_job_binary(self.swift_job_binary_with_extra)
# check for job binary in list
- _, binaries = self.client.list_job_binaries()
+ binaries = self.client.list_job_binaries()
binaries_info = [(binary['id'], binary['name']) for binary in binaries]
self.assertIn(binary_info, binaries_info)
@test.attr(type='smoke')
+ @test.idempotent_id('2d4a670f-e8f1-413c-b5ac-50c1bfe9e1b1')
def test_swift_job_binary_get(self):
binary_id, binary_name = (
self._create_job_binary(self.swift_job_binary_with_extra))
# check job binary fetch by id
- _, binary = self.client.get_job_binary(binary_id)
+ binary = self.client.get_job_binary(binary_id)
self.assertEqual(binary_name, binary['name'])
self.assertDictContainsSubset(self.swift_job_binary, binary)
@test.attr(type='smoke')
+ @test.idempotent_id('9b0e8f38-04f3-4616-b399-cfa7eb2677ed')
def test_swift_job_binary_delete(self):
binary_id, _ = (
self._create_job_binary(self.swift_job_binary_with_extra))
@@ -101,29 +105,33 @@
self.client.delete_job_binary(binary_id)
@test.attr(type='smoke')
+ @test.idempotent_id('63662f6d-8291-407e-a6fc-f654522ebab6')
def test_internal_db_job_binary_create(self):
self._create_job_binary(self.internal_db_job_binary)
@test.attr(type='smoke')
+ @test.idempotent_id('38731e7b-6d9d-4ffa-8fd1-193c453e88b1')
def test_internal_db_job_binary_list(self):
binary_info = self._create_job_binary(self.internal_db_job_binary)
# check for job binary in list
- _, binaries = self.client.list_job_binaries()
+ binaries = self.client.list_job_binaries()
binaries_info = [(binary['id'], binary['name']) for binary in binaries]
self.assertIn(binary_info, binaries_info)
@test.attr(type='smoke')
+ @test.idempotent_id('1b32199b-c3f5-43e1-a37a-3797e57b7066')
def test_internal_db_job_binary_get(self):
binary_id, binary_name = (
self._create_job_binary(self.internal_db_job_binary))
# check job binary fetch by id
- _, binary = self.client.get_job_binary(binary_id)
+ binary = self.client.get_job_binary(binary_id)
self.assertEqual(binary_name, binary['name'])
self.assertDictContainsSubset(self.internal_db_job_binary, binary)
@test.attr(type='smoke')
+ @test.idempotent_id('3c42b0c3-3e03-46a5-adf0-df0650271a4e')
def test_internal_db_job_binary_delete(self):
binary_id, _ = self._create_job_binary(self.internal_db_job_binary)
@@ -131,6 +139,7 @@
self.client.delete_job_binary(binary_id)
@test.attr(type='smoke')
+ @test.idempotent_id('d5d47659-7e2c-4ea7-b292-5b3e559e8587')
def test_job_binary_get_data(self):
binary_id, _ = self._create_job_binary(self.internal_db_job_binary)
diff --git a/tempest/api/data_processing/test_job_binary_internals.py b/tempest/api/data_processing/test_job_binary_internals.py
index 7e99867..3d76ebe 100644
--- a/tempest/api/data_processing/test_job_binary_internals.py
+++ b/tempest/api/data_processing/test_job_binary_internals.py
@@ -47,27 +47,31 @@
return resp_body['id'], binary_name
@test.attr(type='smoke')
+ @test.idempotent_id('249c4dc2-946f-4939-83e6-212ddb6ea0be')
def test_job_binary_internal_create(self):
self._create_job_binary_internal()
@test.attr(type='smoke')
+ @test.idempotent_id('1e3c2ecd-5673-499d-babe-4fe2fcdf64ee')
def test_job_binary_internal_list(self):
binary_info = self._create_job_binary_internal()
# check for job binary internal in list
- _, binaries = self.client.list_job_binary_internals()
+ binaries = self.client.list_job_binary_internals()
binaries_info = [(binary['id'], binary['name']) for binary in binaries]
self.assertIn(binary_info, binaries_info)
@test.attr(type='smoke')
+ @test.idempotent_id('a2046a53-386c-43ab-be35-df54b19db776')
def test_job_binary_internal_get(self):
binary_id, binary_name = self._create_job_binary_internal()
# check job binary internal fetch by id
- _, binary = self.client.get_job_binary_internal(binary_id)
+ binary = self.client.get_job_binary_internal(binary_id)
self.assertEqual(binary_name, binary['name'])
@test.attr(type='smoke')
+ @test.idempotent_id('b3568c33-4eed-40d5-aae4-6ff3b2ac58f5')
def test_job_binary_internal_delete(self):
binary_id, _ = self._create_job_binary_internal()
@@ -75,6 +79,7 @@
self.client.delete_job_binary_internal(binary_id)
@test.attr(type='smoke')
+ @test.idempotent_id('8871f2b0-5782-4d66-9bb9-6f95bcb839ea')
def test_job_binary_internal_get_data(self):
binary_id, _ = self._create_job_binary_internal()
diff --git a/tempest/api/data_processing/test_jobs.py b/tempest/api/data_processing/test_jobs.py
index 5af2eef..83eb54d 100644
--- a/tempest/api/data_processing/test_jobs.py
+++ b/tempest/api/data_processing/test_jobs.py
@@ -61,27 +61,31 @@
return resp_body['id'], job_name
@test.attr(type='smoke')
+ @test.idempotent_id('8cf785ca-adf4-473d-8281-fb9a5efa3073')
def test_job_create(self):
self._create_job()
@test.attr(type='smoke')
+ @test.idempotent_id('41e253fe-b02a-41a0-b186-5ff1f0463ba3')
def test_job_list(self):
job_info = self._create_job()
# check for job in list
- _, jobs = self.client.list_jobs()
+ jobs = self.client.list_jobs()
jobs_info = [(job['id'], job['name']) for job in jobs]
self.assertIn(job_info, jobs_info)
@test.attr(type='smoke')
+ @test.idempotent_id('3faf17fa-bc94-4a60-b1c3-79e53674c16c')
def test_job_get(self):
job_id, job_name = self._create_job()
# check job fetch by id
- _, job = self.client.get_job(job_id)
+ job = self.client.get_job(job_id)
self.assertEqual(job_name, job['name'])
@test.attr(type='smoke')
+ @test.idempotent_id('dff85e62-7dda-4ad8-b1ee-850adecb0c6e')
def test_job_delete(self):
job_id, _ = self._create_job()
diff --git a/tempest/api/data_processing/test_node_group_templates.py b/tempest/api/data_processing/test_node_group_templates.py
index f3f59fc..9d84218 100644
--- a/tempest/api/data_processing/test_node_group_templates.py
+++ b/tempest/api/data_processing/test_node_group_templates.py
@@ -61,29 +61,33 @@
return resp_body['id'], template_name
@test.attr(type='smoke')
+ @test.idempotent_id('63164051-e46d-4387-9741-302ef4791cbd')
def test_node_group_template_create(self):
self._create_node_group_template()
@test.attr(type='smoke')
+ @test.idempotent_id('eb39801d-2612-45e5-88b1-b5d70b329185')
def test_node_group_template_list(self):
template_info = self._create_node_group_template()
# check for node group template in list
- _, templates = self.client.list_node_group_templates()
+ templates = self.client.list_node_group_templates()
templates_info = [(template['id'], template['name'])
for template in templates]
self.assertIn(template_info, templates_info)
@test.attr(type='smoke')
+ @test.idempotent_id('6ee31539-a708-466f-9c26-4093ce09a836')
def test_node_group_template_get(self):
template_id, template_name = self._create_node_group_template()
# check node group template fetch by id
- _, template = self.client.get_node_group_template(template_id)
+ template = self.client.get_node_group_template(template_id)
self.assertEqual(template_name, template['name'])
self.assertDictContainsSubset(self.node_group_template, template)
@test.attr(type='smoke')
+ @test.idempotent_id('f4f5cb82-708d-4031-81c4-b0618a706a2f')
def test_node_group_template_delete(self):
template_id, _ = self._create_node_group_template()
diff --git a/tempest/api/data_processing/test_plugins.py b/tempest/api/data_processing/test_plugins.py
index 4b4ec48..92a5bd0 100644
--- a/tempest/api/data_processing/test_plugins.py
+++ b/tempest/api/data_processing/test_plugins.py
@@ -25,7 +25,7 @@
It ensures main plugins availability.
"""
- _, plugins = self.client.list_plugins()
+ plugins = self.client.list_plugins()
plugins_names = [plugin['name'] for plugin in plugins]
for enabled_plugin in CONF.data_processing_feature_enabled.plugins:
self.assertIn(enabled_plugin, plugins_names)
@@ -33,18 +33,20 @@
return plugins_names
@test.attr(type='smoke')
+ @test.idempotent_id('01a005a3-426c-4c0b-9617-d09475403e09')
def test_plugin_list(self):
self._list_all_plugin_names()
@test.attr(type='smoke')
+ @test.idempotent_id('53cf6487-2cfb-4a6f-8671-97c542c6e901')
def test_plugin_get(self):
for plugin_name in self._list_all_plugin_names():
- _, plugin = self.client.get_plugin(plugin_name)
+ plugin = self.client.get_plugin(plugin_name)
self.assertEqual(plugin_name, plugin['name'])
for plugin_version in plugin['versions']:
- _, detailed_plugin = self.client.get_plugin(plugin_name,
- plugin_version)
+ detailed_plugin = self.client.get_plugin(plugin_name,
+ plugin_version)
self.assertEqual(plugin_name, detailed_plugin['name'])
# check that required image tags contains name and version
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index dd4c684..31c5d2a 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -24,22 +24,30 @@
class BaseDatabaseTest(tempest.test.BaseTestCase):
"""Base test case class for all Database API tests."""
- _interface = 'json'
-
@classmethod
- def resource_setup(cls):
- super(BaseDatabaseTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(BaseDatabaseTest, cls).skip_checks()
if not CONF.service_available.trove:
skip_msg = ("%s skipped as trove is not available" % cls.__name__)
raise cls.skipException(skip_msg)
- cls.catalog_type = CONF.database.catalog_type
- cls.db_flavor_ref = CONF.database.db_flavor_ref
- cls.db_current_version = CONF.database.db_current_version
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseDatabaseTest, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
- os = cls.get_client_manager()
- cls.os = os
+ @classmethod
+ def setup_clients(cls):
+ super(BaseDatabaseTest, cls).setup_clients()
cls.database_flavors_client = cls.os.database_flavors_client
cls.os_flavors_client = cls.os.flavors_client
cls.database_limits_client = cls.os.database_limits_client
cls.database_versions_client = cls.os.database_versions_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseDatabaseTest, cls).resource_setup()
+
+ cls.catalog_type = CONF.database.catalog_type
+ cls.db_flavor_ref = CONF.database.db_flavor_ref
+ cls.db_current_version = CONF.database.db_current_version
diff --git a/tempest/api/database/flavors/test_flavors.py b/tempest/api/database/flavors/test_flavors.py
index ed172e9..eeb472c 100644
--- a/tempest/api/database/flavors/test_flavors.py
+++ b/tempest/api/database/flavors/test_flavors.py
@@ -20,24 +20,26 @@
class DatabaseFlavorsTest(base.BaseDatabaseTest):
@classmethod
- def resource_setup(cls):
- super(DatabaseFlavorsTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(DatabaseFlavorsTest, cls).setup_clients()
cls.client = cls.database_flavors_client
@test.attr(type='smoke')
+ @test.idempotent_id('c94b825e-0132-4686-8049-8a4a2bc09525')
def test_get_db_flavor(self):
# The expected flavor details should be returned
- _, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+ flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
self.assertEqual(self.db_flavor_ref, str(flavor['id']))
self.assertIn('ram', flavor)
self.assertIn('links', flavor)
self.assertIn('name', flavor)
@test.attr(type='smoke')
+ @test.idempotent_id('685025d6-0cec-4673-8a8d-995cb8e0d3bb')
def test_list_db_flavors(self):
- _, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+ flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
# List of all flavors should contain the expected flavor
- _, flavors = self.client.list_db_flavors()
+ flavors = self.client.list_db_flavors()
self.assertIn(flavor, flavors)
def _check_values(self, names, db_flavor, os_flavor, in_db=True):
@@ -52,15 +54,16 @@
self.assertNotIn(name, db_flavor)
@test.attr(type='smoke')
+ @test.idempotent_id('afb2667f-4ec2-4925-bcb7-313fdcffb80d')
@test.services('compute')
def test_compare_db_flavors_with_os(self):
- _, db_flavors = self.client.list_db_flavors()
+ db_flavors = self.client.list_db_flavors()
os_flavors = self.os_flavors_client.list_flavors_with_detail()
self.assertEqual(len(os_flavors), len(db_flavors),
"OS flavors %s do not match DB flavors %s" %
(os_flavors, db_flavors))
for os_flavor in os_flavors:
- _, db_flavor =\
+ db_flavor =\
self.client.get_db_flavor_details(os_flavor['id'])
self._check_values(['id', 'name', 'ram'], db_flavor, os_flavor)
self._check_values(['disk', 'vcpus', 'swap'], db_flavor, os_flavor,
diff --git a/tempest/api/database/flavors/test_flavors_negative.py b/tempest/api/database/flavors/test_flavors_negative.py
index 9f14cce..1b2c88c 100644
--- a/tempest/api/database/flavors/test_flavors_negative.py
+++ b/tempest/api/database/flavors/test_flavors_negative.py
@@ -13,20 +13,22 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.database import base
-from tempest import exceptions
from tempest import test
class DatabaseFlavorsNegativeTest(base.BaseDatabaseTest):
@classmethod
- def resource_setup(cls):
- super(DatabaseFlavorsNegativeTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(DatabaseFlavorsNegativeTest, cls).setup_clients()
cls.client = cls.database_flavors_client
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f8e7b721-373f-4a64-8e9c-5327e975af3e')
def test_get_non_existent_db_flavor(self):
# flavor details are not returned for non-existent flavors
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_db_flavor_details, -1)
diff --git a/tempest/api/database/limits/test_limits.py b/tempest/api/database/limits/test_limits.py
index 30d0a77..7d2fbac 100644
--- a/tempest/api/database/limits/test_limits.py
+++ b/tempest/api/database/limits/test_limits.py
@@ -18,7 +18,6 @@
class DatabaseLimitsTest(base.BaseDatabaseTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -26,10 +25,11 @@
cls.client = cls.database_limits_client
@test.attr(type='smoke')
+ @test.idempotent_id('73024538-f316-4829-b3e9-b459290e137a')
def test_absolute_limits(self):
# Test to verify if all absolute limit paramaters are
# present when verb is ABSOLUTE
- _, limits = self.client.list_db_limits()
+ limits = self.client.list_db_limits()
expected_abs_limits = ['max_backups', 'max_volumes',
'max_instances', 'verb']
absolute_limit = [l for l in limits
diff --git a/tempest/api/database/versions/test_versions.py b/tempest/api/database/versions/test_versions.py
index 80fcecf..55d8246 100644
--- a/tempest/api/database/versions/test_versions.py
+++ b/tempest/api/database/versions/test_versions.py
@@ -18,16 +18,16 @@
class DatabaseVersionsTest(base.BaseDatabaseTest):
- _interface = 'json'
@classmethod
- def resource_setup(cls):
- super(DatabaseVersionsTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(DatabaseVersionsTest, cls).setup_clients()
cls.client = cls.database_versions_client
@test.attr(type='smoke')
+ @test.idempotent_id('6952cd77-90cd-4dca-bb60-8e2c797940cf')
def test_list_db_versions(self):
- _, versions = self.client.list_db_versions()
+ versions = self.client.list_db_versions()
self.assertTrue(len(versions) > 0, "No database versions found")
# List of all versions should contain the current version, and there
# should only be one 'current' version
diff --git a/tempest/services/identity/json/__init__.py b/tempest/api/identity/admin/v2/__init__.py
similarity index 100%
copy from tempest/services/identity/json/__init__.py
copy to tempest/api/identity/admin/v2/__init__.py
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/v2/test_roles.py
similarity index 91%
rename from tempest/api/identity/admin/test_roles.py
rename to tempest/api/identity/admin/v2/test_roles.py
index c6c7dc3..3eb6c08 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/v2/test_roles.py
@@ -21,7 +21,6 @@
class RolesTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -47,6 +46,7 @@
self.assertTrue(found, "assigned role was not in list")
@test.attr(type='gate')
+ @test.idempotent_id('75d9593f-50b7-4fcf-bd64-e3fb4a278e23')
def test_list_roles(self):
"""Return a list of all roles."""
body = self.client.list_roles()
@@ -55,6 +55,7 @@
self.assertEqual(len(found), len(self.data.roles))
@test.attr(type='gate')
+ @test.idempotent_id('c62d909d-6c21-48c0-ae40-0a0760e6db5e')
def test_role_create_delete(self):
"""Role should be created, verified, and deleted."""
role_name = data_utils.rand_name(name='role-test-')
@@ -72,6 +73,7 @@
self.assertFalse(any(found))
@test.attr(type='gate')
+ @test.idempotent_id('db6870bd-a6ed-43be-a9b1-2f10a5c9994f')
def test_get_role_by_id(self):
"""Get a role by its id."""
self.data.setup_test_role()
@@ -82,6 +84,7 @@
self.assertEqual(role_name, body['name'])
@test.attr(type='gate')
+ @test.idempotent_id('0146f675-ffbd-4208-b3a4-60eb628dbc5e')
def test_assign_user_role(self):
"""Assign a role to a user on a tenant."""
(user, tenant, role) = self._get_role_params()
@@ -90,6 +93,7 @@
self.assert_role_in_role_list(role, roles)
@test.attr(type='gate')
+ @test.idempotent_id('f0b9292c-d3ba-4082-aa6c-440489beef69')
def test_remove_user_role(self):
"""Remove a role assigned to a user on a tenant."""
(user, tenant, role) = self._get_role_params()
@@ -99,6 +103,7 @@
user_role['id'])
@test.attr(type='gate')
+ @test.idempotent_id('262e1e3e-ed71-4edd-a0e5-d64e83d66d05')
def test_list_user_roles(self):
"""List roles assigned to a user on tenant."""
(user, tenant, role) = self._get_role_params()
diff --git a/tempest/api/identity/admin/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
similarity index 78%
rename from tempest/api/identity/admin/test_roles_negative.py
rename to tempest/api/identity/admin/v2/test_roles_negative.py
index 58f726a..be9fb52 100644
--- a/tempest/api/identity/admin/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -13,16 +13,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
def _get_role_params(self):
self.data.setup_test_user()
@@ -33,62 +32,70 @@
return (user, tenant, role)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d5d5f1df-f8ca-4de0-b2ef-259c1cc67025')
def test_list_roles_by_unauthorized_user(self):
# Non-administrator user should not be able to list roles
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_roles)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('11a3c7da-df6c-40c2-abc2-badd682edf9f')
def test_list_roles_request_without_token(self):
# Request to list roles without a valid token should fail
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
+ self.assertRaises(lib_exc.Unauthorized, self.client.list_roles)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c0b89e56-accc-4c73-85f8-9c0f866104c1')
def test_role_create_blank_name(self):
# Should not be able to create a role with a blank name
- self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
+ self.assertRaises(lib_exc.BadRequest, self.client.create_role, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('585c8998-a8a4-4641-a5dd-abef7a8ced00')
def test_create_role_by_unauthorized_user(self):
# Non-administrator user should not be able to create role
role_name = data_utils.rand_name(name='role-')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.create_role, role_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a7edd17a-e34a-4aab-8bb7-fa6f498645b8')
def test_create_role_request_without_token(self):
# Request to create role without a valid token should fail
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
role_name = data_utils.rand_name(name='role-')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.create_role, role_name)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c0cde2c8-81c1-4bb0-8fe2-cf615a3547a8')
def test_role_create_duplicate(self):
# Role names should be unique
role_name = data_utils.rand_name(name='role-dup-')
body = self.client.create_role(role_name)
role1_id = body.get('id')
self.addCleanup(self.client.delete_role, role1_id)
- self.assertRaises(exceptions.Conflict, self.client.create_role,
+ self.assertRaises(lib_exc.Conflict, self.client.create_role,
role_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('15347635-b5b1-4a87-a280-deb2bd6d865e')
def test_delete_role_by_unauthorized_user(self):
# Non-administrator user should not be able to delete role
role_name = data_utils.rand_name(name='role-')
body = self.client.create_role(role_name)
self.data.roles.append(body)
role_id = body.get('id')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.delete_role, role_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('44b60b20-70de-4dac-beaf-a3fc2650a16b')
def test_delete_role_request_without_token(self):
# Request to delete role without a valid token should fail
role_name = data_utils.rand_name(name='role-')
@@ -97,63 +104,70 @@
role_id = body.get('id')
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.delete_role,
role_id)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('38373691-8551-453a-b074-4260ad8298ef')
def test_delete_role_non_existent(self):
# Attempt to delete a non existent role should fail
non_existent_role = str(uuid.uuid4().hex)
- self.assertRaises(exceptions.NotFound, self.client.delete_role,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_role,
non_existent_role)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('391df5cf-3ec3-46c9-bbe5-5cb58dd4dc41')
def test_assign_user_role_by_unauthorized_user(self):
# Non-administrator user should not be authorized to
# assign a role to user
(user, tenant, role) = self._get_role_params()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.assign_user_role,
tenant['id'], user['id'], role['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f0d2683c-5603-4aee-95d7-21420e87cfd8')
def test_assign_user_role_request_without_token(self):
# Request to assign a role to a user without a valid token
(user, tenant, role) = self._get_role_params()
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.assign_user_role, tenant['id'],
user['id'], role['id'])
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('99b297f6-2b5d-47c7-97a9-8b6bb4f91042')
def test_assign_user_role_for_non_existent_role(self):
# Attempt to assign a non existent role to user should fail
(user, tenant, role) = self._get_role_params()
non_existent_role = str(uuid.uuid4().hex)
- self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.assign_user_role,
tenant['id'], user['id'], non_existent_role)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b2285aaa-9e76-4704-93a9-7a8acd0a6c8f')
def test_assign_user_role_for_non_existent_tenant(self):
# Attempt to assign a role on a non existent tenant should fail
(user, tenant, role) = self._get_role_params()
non_existent_tenant = str(uuid.uuid4().hex)
- self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.assign_user_role,
non_existent_tenant, user['id'], role['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5c3132cd-c4c8-4402-b5ea-71eb44e97793')
def test_assign_duplicate_user_role(self):
# Duplicate user role should not get assigned
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
+ self.assertRaises(lib_exc.Conflict, self.client.assign_user_role,
tenant['id'], user['id'], role['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d0537987-0977-448f-a435-904c15de7298')
def test_remove_user_role_by_unauthorized_user(self):
# Non-administrator user should not be authorized to
# remove a user's role
@@ -161,11 +175,12 @@
self.client.assign_user_role(tenant['id'],
user['id'],
role['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.remove_user_role,
tenant['id'], user['id'], role['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('cac81cf4-c1d2-47dc-90d3-f2b7eb572286')
def test_remove_user_role_request_without_token(self):
# Request to remove a user's role without a valid token
(user, tenant, role) = self._get_role_params()
@@ -174,12 +189,13 @@
role['id'])
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.remove_user_role, tenant['id'],
user['id'], role['id'])
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ab32d759-cd16-41f1-a86e-44405fa9f6d2')
def test_remove_user_role_non_existent_role(self):
# Attempt to delete a non existent role from a user should fail
(user, tenant, role) = self._get_role_params()
@@ -187,10 +203,11 @@
user['id'],
role['id'])
non_existent_role = str(uuid.uuid4().hex)
- self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.remove_user_role,
tenant['id'], user['id'], non_existent_role)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('67a679ec-03dd-4551-bbfc-d1c93284f023')
def test_remove_user_role_non_existent_tenant(self):
# Attempt to remove a role from a non existent tenant should fail
(user, tenant, role) = self._get_role_params()
@@ -198,27 +215,29 @@
user['id'],
role['id'])
non_existent_tenant = str(uuid.uuid4().hex)
- self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
+ self.assertRaises(lib_exc.NotFound, self.client.remove_user_role,
non_existent_tenant, user['id'], role['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7391ab4c-06f3-477a-a64a-c8e55ce89837')
def test_list_user_roles_by_unauthorized_user(self):
# Non-administrator user should not be authorized to list
# a user's roles
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_user_roles, tenant['id'],
user['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('682adfb2-fd5f-4b0a-a9ca-322e9bebb907')
def test_list_user_roles_request_without_token(self):
# Request to list user's roles without a valid token should fail
(user, tenant, role) = self._get_role_params()
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
try:
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.client.list_user_roles, tenant['id'],
user['id'])
finally:
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/v2/test_services.py
similarity index 92%
rename from tempest/api/identity/admin/test_services.py
rename to tempest/api/identity/admin/v2/test_services.py
index 03d6e35..035f5f8 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -14,24 +14,24 @@
# under the License.
from six import moves
+from tempest_lib import exceptions as lib_exc
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ServicesTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
def _del_service(self, service_id):
# Deleting the service created in this method
self.client.delete_service(service_id)
# Checking whether service is deleted successfully
- self.assertRaises(exceptions.NotFound, self.client.get_service,
+ self.assertRaises(lib_exc.NotFound, self.client.get_service,
service_id)
@test.attr(type='smoke')
+ @test.idempotent_id('84521085-c6e6-491c-9a08-ec9f70f90110')
def test_create_get_delete_service(self):
# GET Service
# Creating a Service
@@ -64,6 +64,7 @@
service_data['description'])
@test.attr(type='gate')
+ @test.idempotent_id('5d3252c8-e555-494b-a6c8-e11d7335da42')
def test_create_service_without_description(self):
# Create a service only with name and type
name = data_utils.rand_name('service-')
@@ -77,6 +78,7 @@
self.assertEqual(type, service['type'])
@test.attr(type='smoke')
+ @test.idempotent_id('34ea6489-012d-4a86-9038-1287cadd5eca')
def test_list_services(self):
# Create, List, Verify and Delete Services
services = []
diff --git a/tempest/api/identity/admin/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
similarity index 75%
rename from tempest/api/identity/admin/test_tenant_negative.py
rename to tempest/api/identity/admin/v2/test_tenant_negative.py
index 75f0152..8346a3d 100644
--- a/tempest/api/identity/admin/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -13,41 +13,44 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class TenantsNegativeTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ca9bb202-63dd-4240-8a07-8ef9c19c04bb')
def test_list_tenants_by_unauthorized_user(self):
# Non-administrator user should not be able to list tenants
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_tenants)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('df33926c-1c96-4d8d-a762-79cc6b0c3cf4')
def test_list_tenant_request_without_token(self):
# Request to list tenants without a valid token should fail
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.list_tenants)
+ self.assertRaises(lib_exc.Unauthorized, self.client.list_tenants)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('162ba316-f18b-4987-8c0c-fd9140cd63ed')
def test_tenant_delete_by_unauthorized_user(self):
# Non-administrator user should not be able to delete a tenant
tenant_name = data_utils.rand_name(name='tenant-')
tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.delete_tenant, tenant['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e450db62-2e9d-418f-893a-54772d6386b1')
def test_tenant_delete_request_without_token(self):
# Request to delete a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant-')
@@ -55,17 +58,19 @@
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.delete_tenant,
+ self.assertRaises(lib_exc.Unauthorized, self.client.delete_tenant,
tenant['id'])
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9c9a2aed-6e3c-467a-8f5c-89da9d1b516b')
def test_delete_non_existent_tenant(self):
# Attempt to delete a non existent tenant should fail
- self.assertRaises(exceptions.NotFound, self.client.delete_tenant,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_tenant,
str(uuid.uuid4().hex))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('af16f44b-a849-46cb-9f13-a751c388f739')
def test_tenant_create_duplicate(self):
# Tenant names should be unique
tenant_name = data_utils.rand_name(name='tenant-')
@@ -76,55 +81,62 @@
self.addCleanup(self.client.delete_tenant, tenant1_id)
self.addCleanup(self.data.tenants.remove, tenant)
- self.assertRaises(exceptions.Conflict, self.client.create_tenant,
+ self.assertRaises(lib_exc.Conflict, self.client.create_tenant,
tenant_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d26b278a-6389-4702-8d6e-5980d80137e0')
def test_create_tenant_by_unauthorized_user(self):
# Non-administrator user should not be authorized to create a tenant
tenant_name = data_utils.rand_name(name='tenant-')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.create_tenant, tenant_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a3ee9d7e-6920-4dd5-9321-d4b2b7f0a638')
def test_create_tenant_request_without_token(self):
# Create tenant request without a token should not be authorized
tenant_name = data_utils.rand_name(name='tenant-')
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.create_tenant,
+ self.assertRaises(lib_exc.Unauthorized, self.client.create_tenant,
tenant_name)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5a2e4ca9-b0c0-486c-9c48-64a94fba2395')
def test_create_tenant_with_empty_name(self):
# Tenant name should not be empty
- self.assertRaises(exceptions.BadRequest, self.client.create_tenant,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_tenant,
name='')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('2ff18d1e-dfe3-4359-9dc3-abf582c196b9')
def test_create_tenants_name_length_over_64(self):
# Tenant name length should not be greater than 64 characters
tenant_name = 'a' * 65
- self.assertRaises(exceptions.BadRequest, self.client.create_tenant,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_tenant,
tenant_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bd20dc2a-9557-4db7-b755-f48d952ad706')
def test_update_non_existent_tenant(self):
# Attempt to update a non existent tenant should fail
- self.assertRaises(exceptions.NotFound, self.client.update_tenant,
+ self.assertRaises(lib_exc.NotFound, self.client.update_tenant,
str(uuid.uuid4().hex))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('41704dc5-c5f7-4f79-abfa-76e6fedc570b')
def test_tenant_update_by_unauthorized_user(self):
# Non-administrator user should not be able to update a tenant
tenant_name = data_utils.rand_name(name='tenant-')
tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.update_tenant, tenant['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7a421573-72c7-4c22-a98e-ce539219c657')
def test_tenant_update_request_without_token(self):
# Request to update a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant-')
@@ -132,6 +144,6 @@
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.update_tenant,
+ self.assertRaises(lib_exc.Unauthorized, self.client.update_tenant,
tenant['id'])
self.client.auth_provider.clear_auth()
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/v2/test_tenants.py
similarity index 93%
rename from tempest/api/identity/admin/test_tenants.py
rename to tempest/api/identity/admin/v2/test_tenants.py
index 549e952..3f1c3cd 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/v2/test_tenants.py
@@ -21,9 +21,9 @@
class TenantsTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('16c6e05c-6112-4b0e-b83f-5e43f221b6b0')
def test_tenant_list_delete(self):
# Create several tenants and delete them
tenants = []
@@ -46,6 +46,7 @@
self.assertFalse(any(found), 'Tenants failed to delete')
@test.attr(type='gate')
+ @test.idempotent_id('d25e9f24-1310-4d29-b61b-d91299c21d6d')
def test_tenant_create_with_description(self):
# Create tenant with a description
tenant_name = data_utils.rand_name(name='tenant-')
@@ -66,6 +67,7 @@
self.data.tenants.remove(tenant)
@test.attr(type='gate')
+ @test.idempotent_id('670bdddc-1cd7-41c7-b8e2-751cfb67df50')
def test_tenant_create_enabled(self):
# Create a tenant that is enabled
tenant_name = data_utils.rand_name(name='tenant-')
@@ -82,6 +84,7 @@
self.data.tenants.remove(tenant)
@test.attr(type='gate')
+ @test.idempotent_id('3be22093-b30f-499d-b772-38340e5e16fb')
def test_tenant_create_not_enabled(self):
# Create a tenant that is not enabled
tenant_name = data_utils.rand_name(name='tenant-')
@@ -100,6 +103,7 @@
self.data.tenants.remove(tenant)
@test.attr(type='gate')
+ @test.idempotent_id('781f2266-d128-47f3-8bdb-f70970add238')
def test_tenant_update_name(self):
# Update name attribute of a tenant
t_name1 = data_utils.rand_name(name='tenant-')
@@ -126,6 +130,7 @@
self.data.tenants.remove(tenant)
@test.attr(type='gate')
+ @test.idempotent_id('859fcfe1-3a03-41ef-86f9-b19a47d1cd87')
def test_tenant_update_desc(self):
# Update description attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
@@ -153,6 +158,7 @@
self.data.tenants.remove(tenant)
@test.attr(type='gate')
+ @test.idempotent_id('8fc8981f-f12d-4c66-9972-2bdcf2bc2e1a')
def test_tenant_update_enable(self):
# Update the enabled attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
similarity index 96%
rename from tempest/api/identity/admin/test_tokens.py
rename to tempest/api/identity/admin/v2/test_tokens.py
index bec621c..751f5fd 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -19,9 +19,9 @@
class TokensTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('453ad4d5-e486-4b2f-be72-cffc8149e586')
def test_create_get_delete_token(self):
# get a token by username and password
user_name = data_utils.rand_name(name='user-')
@@ -52,6 +52,7 @@
self.client.delete_token(token_id)
@test.attr(type='gate')
+ @test.idempotent_id('25ba82ee-8a32-4ceb-8f50-8b8c71e8765e')
def test_rescope_token(self):
"""An unscoped token can be requested, that token can be used to
request a scoped token.
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/v2/test_users.py
similarity index 93%
rename from tempest/api/identity/admin/test_users.py
rename to tempest/api/identity/admin/v2/test_users.py
index 25312e8..fc64f67 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -21,7 +21,6 @@
class UsersTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -31,6 +30,7 @@
cls.alt_email = cls.alt_user + '@testmail.tm'
@test.attr(type='smoke')
+ @test.idempotent_id('2d55a71e-da1d-4b43-9c03-d269fd93d905')
def test_create_user(self):
# Create a user
self.data.setup_test_tenant()
@@ -41,6 +41,7 @@
self.assertEqual(self.alt_user, user['name'])
@test.attr(type='smoke')
+ @test.idempotent_id('89d9fdb8-15c2-4304-a429-48715d0af33d')
def test_create_user_with_enabled(self):
# Create a user with enabled : False
self.data.setup_test_tenant()
@@ -54,6 +55,7 @@
self.assertEqual(self.alt_email, user['email'])
@test.attr(type='smoke')
+ @test.idempotent_id('39d05857-e8a5-4ed4-ba83-0b52d3ab97ee')
def test_update_user(self):
# Test case to check if updating of user attributes is successful.
test_user = data_utils.rand_name('test_user_')
@@ -80,6 +82,7 @@
self.assertEqual('false', str(updated_user['enabled']).lower())
@test.attr(type='smoke')
+ @test.idempotent_id('29ed26f4-a74e-4425-9a85-fdb49fa269d2')
def test_delete_user(self):
# Delete a user
test_user = data_utils.rand_name('test_user_')
@@ -90,6 +93,7 @@
self.client.delete_user(user['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('aca696c3-d645-4f45-b728-63646045beb1')
def test_user_authentication(self):
# Valid user's token is authenticated
self.data.setup_test_user()
@@ -102,6 +106,7 @@
self.data.test_tenant)
@test.attr(type='gate')
+ @test.idempotent_id('5d1fa498-4c2d-4732-a8fe-2b054598cfdd')
def test_authentication_request_without_token(self):
# Request for token authentication with a valid token in header
self.data.setup_test_user()
@@ -118,6 +123,7 @@
self.client.auth_provider.clear_auth()
@test.attr(type='smoke')
+ @test.idempotent_id('a149c02e-e5e0-4b89-809e-7e8faf33ccda')
def test_get_users(self):
# Get a list of users and find the test user
self.data.setup_test_user()
@@ -127,6 +133,7 @@
"Could not find %s" % self.data.test_user)
@test.attr(type='gate')
+ @test.idempotent_id('6e317209-383a-4bed-9f10-075b7c82c79a')
def test_list_users_for_tenant(self):
# Return a list of all users for a tenant
self.data.setup_test_tenant()
@@ -157,6 +164,7 @@
', '.join(m_user for m_user in missing_users))
@test.attr(type='gate')
+ @test.idempotent_id('a8b54974-40e1-41c0-b812-50fc90827971')
def test_list_users_with_roles_for_tenant(self):
# Return list of users on tenant when roles are assigned to users
self.data.setup_test_user()
@@ -192,6 +200,7 @@
', '.join(m_user for m_user in missing_users))
@test.attr(type='smoke')
+ @test.idempotent_id('1aeb25ac-6ec5-4d8b-97cb-7ac3567a989f')
def test_update_user_password(self):
# Test case to check if updating of user password is successful.
self.data.setup_test_user()
diff --git a/tempest/api/identity/admin/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
similarity index 76%
rename from tempest/api/identity/admin/test_users_negative.py
rename to tempest/api/identity/admin/v2/test_users_negative.py
index c039da6..f40621b 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -13,16 +13,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import uuid
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -32,46 +31,52 @@
cls.alt_email = cls.alt_user + '@testmail.tm'
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('60a1f5fa-5744-4cdf-82bf-60b7de2d29a4')
def test_create_user_by_unauthorized_user(self):
# Non-administrator should not be authorized to create a user
self.data.setup_test_tenant()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.create_user, self.alt_user,
self.alt_password, self.data.tenant['id'],
self.alt_email)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d80d0c2f-4514-4d1e-806d-0930dfc5a187')
def test_create_user_with_empty_name(self):
# User with an empty name should not be created
self.data.setup_test_tenant()
- self.assertRaises(exceptions.BadRequest, self.client.create_user, '',
+ self.assertRaises(lib_exc.BadRequest, self.client.create_user, '',
self.alt_password, self.data.tenant['id'],
self.alt_email)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7704b4f3-3b75-4b82-87cc-931d41c8f780')
def test_create_user_with_name_length_over_255(self):
# Length of user name filed should be restricted to 255 characters
self.data.setup_test_tenant()
- self.assertRaises(exceptions.BadRequest, self.client.create_user,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_user,
'a' * 256, self.alt_password,
self.data.tenant['id'], self.alt_email)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('57ae8558-120c-4723-9308-3751474e7ecf')
def test_create_user_with_duplicate_name(self):
# Duplicate user should not be created
self.data.setup_test_user()
- self.assertRaises(exceptions.Conflict, self.client.create_user,
+ self.assertRaises(lib_exc.Conflict, self.client.create_user,
self.data.test_user, self.data.test_password,
self.data.tenant['id'], self.data.test_email)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
def test_create_user_for_non_existent_tenant(self):
# Attempt to create a user in a non-existent tenant should fail
- self.assertRaises(exceptions.NotFound, self.client.create_user,
+ self.assertRaises(lib_exc.NotFound, self.client.create_user,
self.alt_user, self.alt_password, '49ffgg99999',
self.alt_email)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('55bbb103-d1ae-437b-989b-bcdf8175c1f4')
def test_create_user_request_without_a_token(self):
# Request to create a user without a valid token should fail
self.data.setup_test_tenant()
@@ -79,7 +84,7 @@
token = self.client.auth_provider.get_token()
# Delete the token from database
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.create_user,
+ self.assertRaises(lib_exc.Unauthorized, self.client.create_user,
self.alt_user, self.alt_password,
self.data.tenant['id'], self.alt_email)
@@ -87,24 +92,27 @@
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('23a2f3da-4a1a-41da-abdd-632328a861ad')
def test_create_user_with_enabled_non_bool(self):
# Attempt to create a user with valid enabled para should fail
self.data.setup_test_tenant()
name = data_utils.rand_name('test_user_')
- self.assertRaises(exceptions.BadRequest, self.client.create_user,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_user,
name, self.alt_password,
self.data.tenant['id'],
self.alt_email, enabled=3)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3d07e294-27a0-4144-b780-a2a1bf6fee19')
def test_update_user_for_non_existent_user(self):
# Attempt to update a user non-existent user should fail
user_name = data_utils.rand_name('user-')
non_existent_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound, self.client.update_user,
+ self.assertRaises(lib_exc.NotFound, self.client.update_user,
non_existent_id, name=user_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('3cc2a64b-83aa-4b02-88f0-d6ab737c4466')
def test_update_user_request_without_a_token(self):
# Request to update a user without a valid token should fail
@@ -112,34 +120,38 @@
token = self.client.auth_provider.get_token()
# Delete the token from database
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.update_user,
+ self.assertRaises(lib_exc.Unauthorized, self.client.update_user,
self.alt_user)
# Unset the token to allow further tests to generate a new token
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('424868d5-18a7-43e1-8903-a64f95ee3aac')
def test_update_user_by_unauthorized_user(self):
# Non-administrator should not be authorized to update user
self.data.setup_test_tenant()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.update_user, self.alt_user)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d45195d5-33ed-41b9-a452-7d0d6a00f6e9')
def test_delete_users_by_unauthorized_user(self):
# Non-administrator user should not be authorized to delete a user
self.data.setup_test_user()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.delete_user,
self.data.user['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7cc82f7e-9998-4f89-abae-23df36495867')
def test_delete_non_existent_user(self):
# Attempt to delete a non-existent user should fail
- self.assertRaises(exceptions.NotFound, self.client.delete_user,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_user,
'junk12345123')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('57fe1df8-0aa7-46c0-ae9f-c2e785c7504a')
def test_delete_user_request_without_a_token(self):
# Request to delete a user without a valid token should fail
@@ -147,73 +159,81 @@
token = self.client.auth_provider.get_token()
# Delete the token from database
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.delete_user,
+ self.assertRaises(lib_exc.Unauthorized, self.client.delete_user,
self.alt_user)
# Unset the token to allow further tests to generate a new token
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('593a4981-f6d4-460a-99a1-57a78bf20829')
def test_authentication_for_disabled_user(self):
# Disabled user's token should not get authenticated
self.data.setup_test_user()
self.disable_user(self.data.test_user)
- self.assertRaises(exceptions.Unauthorized, self.token_client.auth,
+ self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
self.data.test_user,
self.data.test_password,
self.data.test_tenant)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('440a7a8d-9328-4b7b-83e0-d717010495e4')
def test_authentication_when_tenant_is_disabled(self):
# User's token for a disabled tenant should not be authenticated
self.data.setup_test_user()
self.disable_tenant(self.data.test_tenant)
- self.assertRaises(exceptions.Unauthorized, self.token_client.auth,
+ self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
self.data.test_user,
self.data.test_password,
self.data.test_tenant)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('921f1ad6-7907-40b8-853f-637e7ee52178')
def test_authentication_with_invalid_tenant(self):
# User's token for an invalid tenant should not be authenticated
self.data.setup_test_user()
- self.assertRaises(exceptions.Unauthorized, self.token_client.auth,
+ self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
self.data.test_user,
self.data.test_password,
'junktenant1234')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bde9aecd-3b1c-4079-858f-beb5deaa5b5e')
def test_authentication_with_invalid_username(self):
# Non-existent user's token should not get authenticated
self.data.setup_test_user()
- self.assertRaises(exceptions.Unauthorized, self.token_client.auth,
+ self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
'junkuser123', self.data.test_password,
self.data.test_tenant)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('d5308b33-3574-43c3-8d87-1c090c5e1eca')
def test_authentication_with_invalid_password(self):
# User's token with invalid password should not be authenticated
self.data.setup_test_user()
- self.assertRaises(exceptions.Unauthorized, self.token_client.auth,
+ self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
self.data.test_user, 'junkpass1234',
self.data.test_tenant)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('284192ce-fb7c-4909-a63b-9a502e0ddd11')
def test_get_users_by_unauthorized_user(self):
# Non-administrator user should not be authorized to get user list
self.data.setup_test_user()
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.get_users)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a73591ec-1903-4ffe-be42-282b39fefc9d')
def test_get_users_request_without_token(self):
# Request to get list of users without a valid token should fail
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
- self.assertRaises(exceptions.Unauthorized, self.client.get_users)
+ self.assertRaises(lib_exc.Unauthorized, self.client.get_users)
self.client.auth_provider.clear_auth()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f5d39046-fc5f-425c-b29e-bac2632da28e')
def test_list_users_with_invalid_tenant(self):
# Should not be able to return a list of all
# users for a non-existent tenant
@@ -225,5 +245,5 @@
invalid_id.append('!@#()$%^&*?<>{}[]')
# List the users with invalid tenant id
for invalid in invalid_id:
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.list_users_for_tenant, invalid)
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 6f2f6d4..6fbd544 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -19,7 +19,6 @@
class CredentialsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -52,6 +51,7 @@
self.creds_client.delete_credential(cred_id)
@test.attr(type='smoke')
+ @test.idempotent_id('7cd59bf9-bda4-4c72-9467-d21cab278355')
def test_credentials_create_get_update_delete(self):
keys = [data_utils.rand_name('Access-'),
data_utils.rand_name('Secret-')]
@@ -84,6 +84,7 @@
get_body['blob'][value2])
@test.attr(type='smoke')
+ @test.idempotent_id('13202c00-0021-42a1-88d4-81b44d448aab')
def test_credentials_list_delete(self):
created_cred_ids = list()
fetched_cred_ids = list()
diff --git a/tempest/api/identity/admin/v3/test_default_project_id.py b/tempest/api/identity/admin/v3/test_default_project_id.py
index bd29cb8..f74b30d 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -14,16 +14,19 @@
from tempest import auth
from tempest import clients
from tempest.common.utils import data_utils
+from tempest import config
+from tempest import manager
from tempest import test
+CONF = config.CONF
+
class TestDefaultProjectId (base.BaseIdentityV3AdminTest):
- _interface = 'json'
@classmethod
- def resource_setup(cls):
+ def setup_credentials(cls):
cls.set_network_resources()
- super(TestDefaultProjectId, cls).resource_setup()
+ super(TestDefaultProjectId, cls).setup_credentials()
def _delete_domain(self, domain_id):
# It is necessary to disable the domain before deleting,
@@ -32,6 +35,7 @@
self.client.delete_domain(domain_id)
@test.attr(type='smoke')
+ @test.idempotent_id('d6110661-6a71-49a7-a453-b5e26640ff6d')
def test_default_project_id(self):
# create a domain
dom_name = data_utils.rand_name('dom')
@@ -72,10 +76,9 @@
creds = auth.KeystoneV3Credentials(username=user_name,
password=user_name,
domain_name=dom_name)
- auth_provider = auth.KeystoneV3AuthProvider(creds)
+ auth_provider = manager.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
- admin_client = clients.Manager(interface=self._interface,
- credentials=creds)
+ admin_client = clients.Manager(credentials=creds)
# verify the user's token and see that it is scoped to the project
token, auth_data = admin_client.auth_provider.get_auth()
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index c1bc705..0441f6d 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -20,7 +20,6 @@
class DomainsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
def _delete_domain(self, domain_id):
# It is necessary to disable the domain before deleting,
@@ -29,6 +28,7 @@
self.client.delete_domain(domain_id)
@test.attr(type='smoke')
+ @test.idempotent_id('8cf516ef-2114-48f1-907b-d32726c734d4')
def test_list_domains(self):
# Test to list domains
domain_ids = list()
@@ -48,6 +48,7 @@
self.assertEqual(0, len(missing_doms))
@test.attr(type='smoke')
+ @test.idempotent_id('f2f5b44a-82e8-4dad-8084-0661ea3b18cf')
def test_create_update_delete_domain(self):
d_name = data_utils.rand_name('domain-')
d_desc = data_utils.rand_name('domain-desc-')
@@ -62,10 +63,7 @@
self.assertIsNotNone(domain['id'])
self.assertEqual(d_name, domain['name'])
self.assertEqual(d_desc, domain['description'])
- if self._interface == "json":
- self.assertEqual(True, domain['enabled'])
- else:
- self.assertEqual('true', str(domain['enabled']).lower())
+ self.assertEqual(True, domain['enabled'])
new_desc = data_utils.rand_name('new-desc-')
new_name = data_utils.rand_name('new-name-')
@@ -85,3 +83,16 @@
self.assertEqual(new_name, fetched_domain['name'])
self.assertEqual(new_desc, fetched_domain['description'])
self.assertEqual('true', str(fetched_domain['enabled']).lower())
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('036df86e-bb5d-42c0-a7c2-66b9db3a6046')
+ def test_create_domain_with_disabled_status(self):
+ # Create domain with enabled status as false
+ d_name = data_utils.rand_name('domain-')
+ d_desc = data_utils.rand_name('domain-desc-')
+ domain = self.client.create_domain(
+ d_name, description=d_desc, enabled=False)
+ self.addCleanup(self.client.delete_domain, domain['id'])
+ self.assertEqual(d_name, domain['name'])
+ self.assertFalse(domain['enabled'])
+ self.assertEqual(d_desc, domain['description'])
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index eed0eb5..4a11c95 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -19,13 +19,16 @@
class EndPointsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
+
+ @classmethod
+ def setup_clients(cls):
+ super(EndPointsTestJSON, cls).setup_clients()
+ cls.identity_client = cls.client
+ cls.client = cls.endpoints_client
@classmethod
def resource_setup(cls):
super(EndPointsTestJSON, cls).resource_setup()
- cls.identity_client = cls.client
- cls.client = cls.endpoints_client
cls.service_ids = list()
s_name = data_utils.rand_name('service-')
s_type = data_utils.rand_name('type--')
@@ -54,6 +57,7 @@
super(EndPointsTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('c19ecf90-240e-4e23-9966-21cee3f6a618')
def test_list_endpoints(self):
# Get a list of endpoints
fetched_endpoints = self.client.list_endpoints()
@@ -65,6 +69,7 @@
', '.join(str(e) for e in missing_endpoints))
@test.attr(type='gate')
+ @test.idempotent_id('0e2446d2-c1fd-461b-a729-b9e73e3e3b37')
def test_create_list_delete_endpoint(self):
region = data_utils.rand_name('region')
url = data_utils.rand_url()
@@ -88,6 +93,7 @@
self.assertNotIn(endpoint['id'], fetched_endpoints_id)
@test.attr(type='smoke')
+ @test.idempotent_id('37e8f15e-ee7c-4657-a1e7-f6b61e375eff')
def test_update_endpoint(self):
# Creating an endpoint so as to check update endpoint
# with new values
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 9da0a57..06c8e77 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -14,21 +14,24 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class EndpointsNegativeTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
+
+ @classmethod
+ def setup_clients(cls):
+ super(EndpointsNegativeTestJSON, cls).setup_clients()
+ cls.identity_client = cls.client
+ cls.client = cls.endpoints_client
@classmethod
def resource_setup(cls):
super(EndpointsNegativeTestJSON, cls).resource_setup()
- cls.identity_client = cls.client
- cls.client = cls.endpoints_client
cls.service_ids = list()
s_name = data_utils.rand_name('service-')
s_type = data_utils.rand_name('type--')
@@ -46,22 +49,24 @@
super(EndpointsNegativeTestJSON, cls).resource_cleanup()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ac6c137e-4d3d-448f-8c83-4f13d0942651')
def test_create_with_enabled_False(self):
# Enabled should be a boolean, not a string like 'False'
interface = 'public'
url = data_utils.rand_url()
region = data_utils.rand_name('region')
- self.assertRaises(exceptions.BadRequest, self.client.create_endpoint,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_endpoint,
self.service_id, interface, url, region=region,
force_enabled='False')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9c43181e-0627-484a-8c79-923e8a59598b')
def test_create_with_enabled_True(self):
# Enabled should be a boolean, not a string like 'True'
interface = 'public'
url = data_utils.rand_url()
region = data_utils.rand_name('region')
- self.assertRaises(exceptions.BadRequest, self.client.create_endpoint,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_endpoint,
self.service_id, interface, url, region=region,
force_enabled='True')
@@ -76,15 +81,17 @@
url1, region=region1, enabled=True))
self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
- self.assertRaises(exceptions.BadRequest, self.client.update_endpoint,
+ self.assertRaises(lib_exc.BadRequest, self.client.update_endpoint,
endpoint_for_update['id'], force_enabled=enabled)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('65e41f32-5eb7-498f-a92a-a6ccacf7439a')
def test_update_with_enabled_False(self):
# Enabled should be a boolean, not a string like 'False'
self._assert_update_raises_bad_request('False')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('faba3587-f066-4757-a48e-b4a3f01803bb')
def test_update_with_enabled_True(self):
# Enabled should be a boolean, not a string like 'True'
self._assert_update_raises_bad_request('True')
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index d8c7063..2c70a7c 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -19,13 +19,9 @@
class GroupsV3TestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
-
- @classmethod
- def resource_setup(cls):
- super(GroupsV3TestJSON, cls).resource_setup()
@test.attr(type='smoke')
+ @test.idempotent_id('2e80343b-6c81-4ac3-88c7-452f3e9d5129')
def test_group_create_update_get(self):
name = data_utils.rand_name('Group')
description = data_utils.rand_name('Description')
@@ -49,6 +45,7 @@
self.assertEqual(new_desc, new_group['description'])
@test.attr(type='smoke')
+ @test.idempotent_id('1598521a-2f36-4606-8df9-30772bd51339')
def test_group_users_add_list_delete(self):
name = data_utils.rand_name('Group')
group = self.client.create_group(name)
@@ -73,6 +70,7 @@
self.assertEqual(len(group_users), 0)
@test.attr(type='smoke')
+ @test.idempotent_id('64573281-d26a-4a52-b899-503cb0f4e4ec')
def test_list_user_groups(self):
# create a user
user = self.client.create_user(
@@ -93,6 +91,7 @@
self.assertEqual(2, len(user_groups))
@test.attr(type='smoke')
+ @test.idempotent_id('cc9a57a5-a9ed-4f2d-a29f-4f979a06ec71')
def test_list_groups(self):
# Test to list groups
group_ids = list()
diff --git a/tempest/api/identity/admin/v3/test_list_projects.py b/tempest/api/identity/admin/v3/test_list_projects.py
index c0187f9..ca30b6e 100644
--- a/tempest/api/identity/admin/v3/test_list_projects.py
+++ b/tempest/api/identity/admin/v3/test_list_projects.py
@@ -19,7 +19,6 @@
class ListProjectsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -39,6 +38,7 @@
cls.project_ids.append(cls.p2['id'])
@test.attr(type='gate')
+ @test.idempotent_id('1d830662-22ad-427c-8c3e-4ec854b0af44')
def test_projects_list(self):
# List projects
list_projects = self.client.list_projects()
@@ -48,17 +48,20 @@
self.assertIn(get_project, list_projects)
@test.attr(type='gate')
+ @test.idempotent_id('fab13f3c-f6a6-4b9f-829b-d32fd44fdf10')
def test_list_projects_with_domains(self):
# List projects with domain
self._list_projects_with_params(
{'domain_id': self.data.domain['id']}, 'domain_id')
@test.attr(type='gate')
+ @test.idempotent_id('0fe7a334-675a-4509-b00e-1c4b95d5dae8')
def test_list_projects_with_enabled(self):
# List the projects with enabled
self._list_projects_with_params({'enabled': False}, 'enabled')
@test.attr(type='gate')
+ @test.idempotent_id('fa178524-4e6d-4925-907c-7ab9f42c7e26')
def test_list_projects_with_name(self):
# List projects with name
self._list_projects_with_params({'name': self.p1_name}, 'name')
diff --git a/tempest/api/identity/admin/v3/test_list_users.py b/tempest/api/identity/admin/v3/test_list_users.py
index e728867..1407f38 100644
--- a/tempest/api/identity/admin/v3/test_list_users.py
+++ b/tempest/api/identity/admin/v3/test_list_users.py
@@ -19,7 +19,6 @@
class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
def _list_users_with_params(self, params, key, expected, not_expected):
# Helper method to list users filtered with params and
@@ -52,6 +51,7 @@
cls.data.v3_users.append(cls.non_domain_enabled_user)
@test.attr(type='gate')
+ @test.idempotent_id('08f9aabb-dcfe-41d0-8172-82b5fa0bd73d')
def test_list_user_domains(self):
# List users with domain
params = {'domain_id': self.data.domain['id']}
@@ -60,6 +60,7 @@
self.non_domain_enabled_user)
@test.attr(type='gate')
+ @test.idempotent_id('bff8bf2f-9408-4ef5-b63a-753c8c2124eb')
def test_list_users_with_not_enabled(self):
# List the users with not enabled
params = {'enabled': False}
@@ -68,6 +69,7 @@
self.domain_enabled_user)
@test.attr(type='gate')
+ @test.idempotent_id('c285bb37-7325-4c02-bff3-3da5d946d683')
def test_list_users_with_name(self):
# List users with name
params = {'name': self.domain_enabled_user['name']}
@@ -76,6 +78,7 @@
self.non_domain_enabled_user)
@test.attr(type='gate')
+ @test.idempotent_id('b30d4651-a2ea-4666-8551-0c0e49692635')
def test_list_users(self):
# List users
body = self.client.get_users()
@@ -87,6 +90,7 @@
', '.join(m_user for m_user in missing_users))
@test.attr(type='gate')
+ @test.idempotent_id('b4baa3ae-ac00-4b4e-9e27-80deaad7771f')
def test_get_user(self):
# Get a user detail
user = self.client.get_user(self.data.v3_users[0]['id'])
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 23df13d..900c26e 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -19,12 +19,12 @@
class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
def _delete_policy(self, policy_id):
self.policy_client.delete_policy(policy_id)
@test.attr(type='smoke')
+ @test.idempotent_id('1a0ad286-2d06-4123-ab0d-728893a76201')
def test_list_policies(self):
# Test to list policies
policy_ids = list()
@@ -45,6 +45,7 @@
self.assertEqual(0, len(missing_pols))
@test.attr(type='smoke')
+ @test.idempotent_id('e544703a-2f03-4cf2-9b0f-350782fdb0d3')
def test_create_update_delete_policy(self):
# Test to update policy
blob = data_utils.rand_name('BlobName-')
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 2cf6458..052cf0e 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -19,9 +19,9 @@
class ProjectsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('0ecf465c-0dc4-4532-ab53-91ffeb74d12d')
def test_project_create_with_description(self):
# Create project with a description
project_name = data_utils.rand_name('project-')
@@ -39,6 +39,7 @@
'to be set')
@test.attr(type='gate')
+ @test.idempotent_id('5f50fe07-8166-430b-a882-3b2ee0abe26f')
def test_project_create_with_domain(self):
# Create project with a domain
self.data.setup_test_domain()
@@ -54,6 +55,7 @@
self.assertEqual(self.data.domain['id'], body['domain_id'])
@test.attr(type='gate')
+ @test.idempotent_id('1f66dc76-50cc-4741-a200-af984509e480')
def test_project_create_enabled(self):
# Create a project that is enabled
project_name = data_utils.rand_name('project-')
@@ -68,6 +70,7 @@
self.assertTrue(en2, 'Enable should be True in lookup')
@test.attr(type='gate')
+ @test.idempotent_id('78f96a9c-e0e0-4ee6-a3ba-fbf6dfd03207')
def test_project_create_not_enabled(self):
# Create a project that is not enabled
project_name = data_utils.rand_name('project-')
@@ -83,6 +86,7 @@
'Enable should be False in lookup')
@test.attr(type='gate')
+ @test.idempotent_id('f608f368-048c-496b-ad63-d286c26dab6b')
def test_project_update_name(self):
# Update name attribute of a project
p_name1 = data_utils.rand_name('project-')
@@ -104,6 +108,7 @@
self.assertEqual(resp2_name, resp3_name)
@test.attr(type='gate')
+ @test.idempotent_id('f138b715-255e-4a7d-871d-351e1ef2e153')
def test_project_update_desc(self):
# Update description attribute of a project
p_name = data_utils.rand_name('project-')
@@ -127,6 +132,7 @@
self.assertEqual(resp2_desc, resp3_desc)
@test.attr(type='gate')
+ @test.idempotent_id('b6b25683-c97f-474d-a595-55d410b68100')
def test_project_update_enable(self):
# Update the enabled attribute of a project
p_name = data_utils.rand_name('project-')
@@ -150,6 +156,7 @@
self.assertEqual(resp2_en, resp3_en)
@test.attr(type='gate')
+ @test.idempotent_id('59398d4a-5dc5-4f86-9a4c-c26cc804d6c6')
def test_associate_user_to_project(self):
# Associate a user to a project
# Create a Project
diff --git a/tempest/api/identity/admin/v3/test_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index f5e832b..bc92900 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.py
@@ -13,22 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ProjectsNegativeTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('24c49279-45dd-4155-887a-cb738c2385aa')
def test_list_projects_by_unauthorized_user(self):
# Non-admin user should not be able to list projects
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.non_admin_client.list_projects)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('874c3e84-d174-4348-a16b-8c01f599561b')
def test_project_create_duplicate(self):
# Project names should be unique
project_name = data_utils.rand_name('project-dup-')
@@ -36,41 +38,46 @@
self.data.projects.append(project)
self.assertRaises(
- exceptions.Conflict, self.client.create_project, project_name)
+ lib_exc.Conflict, self.client.create_project, project_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8fba9de2-3e1f-4e77-812a-60cb68f8df13')
def test_create_project_by_unauthorized_user(self):
# Non-admin user should not be authorized to create a project
project_name = data_utils.rand_name('project-')
self.assertRaises(
- exceptions.Unauthorized, self.non_admin_client.create_project,
+ lib_exc.Unauthorized, self.non_admin_client.create_project,
project_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7828db17-95e5-475b-9432-9a51b4aa79a9')
def test_create_project_with_empty_name(self):
# Project name should not be empty
- self.assertRaises(exceptions.BadRequest, self.client.create_project,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_project,
name='')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('502b6ceb-b0c8-4422-bf53-f08fdb21e2f0')
def test_create_projects_name_length_over_64(self):
# Project name length should not be greater than 64 characters
project_name = 'a' * 65
- self.assertRaises(exceptions.BadRequest, self.client.create_project,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_project,
project_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8d68c012-89e0-4394-8d6b-ccd7196def97')
def test_project_delete_by_unauthorized_user(self):
# Non-admin user should not be able to delete a project
project_name = data_utils.rand_name('project-')
project = self.client.create_project(project_name)
self.data.projects.append(project)
self.assertRaises(
- exceptions.Unauthorized, self.non_admin_client.delete_project,
+ lib_exc.Unauthorized, self.non_admin_client.delete_project,
project['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7965b581-60c1-43b7-8169-95d4ab7fc6fb')
def test_delete_non_existent_project(self):
# Attempt to delete a non existent project should fail
- self.assertRaises(exceptions.NotFound, self.client.delete_project,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_project,
data_utils.rand_uuid_hex())
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index c71cbf3..bf3c12e 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -13,20 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class RegionsTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
+
+ @classmethod
+ def setup_clients(cls):
+ super(RegionsTestJSON, cls).setup_clients()
+ cls.client = cls.region_client
@classmethod
def resource_setup(cls):
super(RegionsTestJSON, cls).resource_setup()
cls.setup_regions = list()
- cls.client = cls.region_client
for i in range(2):
r_description = data_utils.rand_name('description-')
region = cls.client.create_region(r_description)
@@ -40,10 +44,11 @@
def _delete_region(self, region_id):
self.client.delete_region(region_id)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_region, region_id)
@test.attr(type='gate')
+ @test.idempotent_id('56186092-82e4-43f2-b954-91013218ba42')
def test_create_update_get_delete_region(self):
r_description = data_utils.rand_name('description-')
region = self.client.create_region(
@@ -68,6 +73,7 @@
region['parent_region_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('2c12c5b5-efcf-4aa5-90c5-bff1ab0cdbe2')
def test_create_region_with_specific_id(self):
# Create a region with a specific id
r_region_id = data_utils.rand_uuid()
@@ -80,6 +86,7 @@
self.assertEqual(r_description, region['description'])
@test.attr(type='gate')
+ @test.idempotent_id('d180bf99-544a-445c-ad0d-0c0d27663796')
def test_list_regions(self):
# Get a list of regions
fetched_regions = self.client.list_regions()
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index b8b309d..24da22a 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -19,7 +19,6 @@
class RolesV3TestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -67,6 +66,7 @@
self.assertIn(role_id, fetched_role_ids)
@test.attr(type='smoke')
+ @test.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
def test_role_create_update_get_list(self):
r_name = data_utils.rand_name('Role-')
role = self.client.create_role(r_name)
@@ -89,6 +89,7 @@
self.assertIn(role['id'], [r['id'] for r in roles])
@test.attr(type='smoke')
+ @test.idempotent_id('c6b80012-fe4a-498b-9ce8-eb391c05169f')
def test_grant_list_revoke_role_to_user_on_project(self):
self.client.assign_user_role_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
@@ -106,6 +107,7 @@
self.project['id'], self.user_body['id'], self.role['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('6c9a2940-3625-43a3-ac02-5dcec62ef3bd')
def test_grant_list_revoke_role_to_user_on_domain(self):
self.client.assign_user_role_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
@@ -123,6 +125,7 @@
self.domain['id'], self.user_body['id'], self.role['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('cbf11737-1904-4690-9613-97bcbb3df1c4')
def test_grant_list_revoke_role_to_group_on_project(self):
# Grant role to group on project
self.client.assign_group_role_on_project(
@@ -140,9 +143,11 @@
self.client.add_group_user(self.group_body['id'], self.user_body['id'])
self.addCleanup(self.client.delete_group_user,
self.group_body['id'], self.user_body['id'])
- body = self.token.auth(self.user_body['id'], self.u_password,
- self.project['name'],
- domain=self.domain['name'])
+ body = self.token.auth(user=self.user_body['id'],
+ password=self.u_password,
+ user_domain=self.domain['name'],
+ project=self.project['name'],
+ project_domain=self.domain['name'])
roles = body['token']['roles']
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])
@@ -151,6 +156,7 @@
self.project['id'], self.group_body['id'], self.role['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('4bf8a70b-e785-413a-ad53-9f91ce02faa7')
def test_grant_list_revoke_role_to_group_on_domain(self):
self.client.assign_group_role_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
@@ -168,6 +174,7 @@
self.domain['id'], self.group_body['id'], self.role['id'])
@test.attr(type='gate')
+ @test.idempotent_id('f5654bcc-08c4-4f71-88fe-05d64e06de94')
def test_list_roles(self):
# Return a list of all roles
body = self.client.list_roles()
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 9e45b50..bf5cc3e 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -13,23 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ServicesTestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
def _del_service(self, service_id):
# Used for deleting the services created in this class
self.service_client.delete_service(service_id)
# Checking whether service is deleted successfully
- self.assertRaises(exceptions.NotFound, self.service_client.get_service,
+ self.assertRaises(lib_exc.NotFound, self.service_client.get_service,
service_id)
@test.attr(type='smoke')
+ @test.idempotent_id('5193aad5-bcb7-411d-85b0-b3b61b96ef06')
def test_create_update_get_service(self):
# Creating a Service
name = data_utils.rand_name('service')
@@ -62,6 +63,7 @@
self.assertDictContainsSubset(update_service, fetched_service)
@test.attr(type='smoke')
+ @test.idempotent_id('d1dcb1a1-2b6b-4da8-bbb8-5532ef6e8269')
def test_create_service_without_description(self):
# Create a service only with name and type
name = data_utils.rand_name('service')
@@ -74,6 +76,7 @@
self.assertDictContainsSubset(expected_data, service)
@test.attr(type='smoke')
+ @test.idempotent_id('e55908e8-360e-439e-8719-c3230a3e179e')
def test_list_services(self):
# Create, List, Verify and Delete Services
service_ids = list()
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index f0acfdf..47f9dbd 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -13,16 +13,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@test.attr(type='smoke')
+ @test.idempotent_id('0f9f5a5f-d5cd-4a86-8a5b-c5ded151f212')
def test_tokens(self):
# Valid user's token is authenticated
# Create a User
@@ -44,10 +45,11 @@
self.assertEqual(token_details['user']['name'], u_name)
# Perform Delete Token
self.client.delete_token(subject_token)
- self.assertRaises(exceptions.NotFound, self.client.get_token,
+ self.assertRaises(lib_exc.NotFound, self.client.get_token,
subject_token)
@test.attr(type='gate')
+ @test.idempotent_id('565fa210-1da1-4563-999b-f7b5b67cf112')
def test_rescope_token(self):
"""Rescope a token.
@@ -108,8 +110,8 @@
# Use the unscoped token to get a scoped token.
token_auth = self.token.auth(token=token_id,
- tenant=project1_name,
- domain='Default')
+ project=project1_name,
+ project_domain='Default')
token1_id = token_auth.response['x-subject-token']
self.assertEqual(orig_expires_at, token_auth['token']['expires_at'],
@@ -138,8 +140,8 @@
# Now get another scoped token using the unscoped token.
token_auth = self.token.auth(token=token_id,
- tenant=project2_name,
- domain='Default')
+ project=project2_name,
+ project_domain='Default')
self.assertEqual(project2['id'],
token_auth['token']['project']['id'])
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index cd28e96..db64a5b 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -13,12 +13,13 @@
import datetime
import re
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.identity import base
-from tempest import auth
from tempest import clients
+from tempest.common import cred_provider
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import timeutils
from tempest import test
@@ -87,13 +88,11 @@
self.assertIsNotNone(self.trustee_user_id)
# Initialize a new client with the trustor credentials
- creds = auth.get_credentials(
+ creds = cred_provider.get_credentials(
username=self.trustor_username,
password=self.trustor_password,
tenant_name=self.trustor_project_name)
- os = clients.Manager(
- credentials=creds,
- interface=self._interface)
+ os = clients.Manager(credentials=creds)
self.trustor_client = os.identity_v3_client
def cleanup_user_and_roles(self):
@@ -120,13 +119,10 @@
summary=False):
self.assertIsNotNone(trust['id'])
self.assertEqual(impersonate, trust['impersonation'])
- # FIXME(shardy): ref bug #1246383 we can't check the
- # microsecond component of the expiry time, because mysql
- # <5.6.4 doesn't support microseconds.
- # expected format 2013-12-20T16:08:36.036987Z
if expires is not None:
- expires_nousec = re.sub(r'\.([0-9]){6}Z', '', expires)
- self.assertTrue(trust['expires_at'].startswith(expires_nousec))
+ # Omit microseconds component of the expiry time
+ trust_expires_at = re.sub(r'\.([0-9]){6}', '', trust['expires_at'])
+ self.assertEqual(expires, trust_expires_at)
else:
self.assertIsNone(trust['expires_at'])
self.assertEqual(self.trustor_user_id, trust['trustor_user_id'])
@@ -166,26 +162,25 @@
self.trust_id, self.delegated_role_id)
# And that we don't find not_delegated_role
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.trustor_client.get_trust_role,
self.trust_id,
self.not_delegated_role_id)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.trustor_client.check_trust_role,
self.trust_id,
self.not_delegated_role_id)
def delete_trust(self):
self.trustor_client.delete_trust(self.trust_id)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.trustor_client.get_trust,
self.trust_id)
self.trust_id = None
class TrustsV3TestJSON(BaseTrustsV3Test):
- _interface = 'json'
def setUp(self):
super(TrustsV3TestJSON, self).setUp()
@@ -193,6 +188,7 @@
self.addCleanup(self.cleanup_user_and_roles)
@test.attr(type='smoke')
+ @test.idempotent_id('5a0a91a4-baef-4a14-baba-59bf4d7fcace')
def test_trust_impersonate(self):
# Test case to check we can create, get and delete a trust
# updates are not supported for trusts
@@ -205,6 +201,7 @@
self.check_trust_roles()
@test.attr(type='smoke')
+ @test.idempotent_id('ed2a8779-a7ac-49dc-afd7-30f32f936ed2')
def test_trust_noimpersonate(self):
# Test case to check we can create, get and delete a trust
# with impersonation=False
@@ -217,11 +214,21 @@
self.check_trust_roles()
@test.attr(type='smoke')
+ @test.idempotent_id('0ed14b66-cefd-4b5c-a964-65759453e292')
def test_trust_expire(self):
# Test case to check we can create, get and delete a trust
# with an expiry specified
expires_at = timeutils.utcnow() + datetime.timedelta(hours=1)
- expires_str = timeutils.isotime(at=expires_at, subsecond=True)
+ # NOTE(ylobankov) In some cases the expiry time may be rounded up
+ # because of microseconds. In fact, it depends on database and its
+ # version. At least MySQL 5.6.16 does this.
+ # For example, when creating a trust, we will set the expiry time of
+ # the trust to 2015-02-17T17:34:01.907051Z. However, if we make a GET
+ # request on the trust, the response will contain the time rounded up
+ # to 2015-02-17T17:34:02.000000Z. That is why we shouldn't set flag
+ # "subsecond" to True when we invoke timeutils.isotime(...) to avoid
+ # problems with rounding.
+ expires_str = timeutils.isotime(at=expires_at)
trust = self.create_trust(expires=expires_str)
self.validate_trust(trust, expires=expires_str)
@@ -233,16 +240,18 @@
self.check_trust_roles()
@test.attr(type='smoke')
+ @test.idempotent_id('3e48f95d-e660-4fa9-85e0-5a3d85594384')
def test_trust_expire_invalid(self):
# Test case to check we can check an invlaid expiry time
# is rejected with the correct error
# with an expiry specified
expires_str = 'bad.123Z'
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_trust,
expires=expires_str)
@test.attr(type='smoke')
+ @test.idempotent_id('6268b345-87ca-47c0-9ce3-37792b43403a')
def test_get_trusts_query(self):
self.create_trust()
trusts_get = self.trustor_client.get_trusts(
@@ -251,6 +260,7 @@
self.validate_trust(trusts_get[0], summary=True)
@test.attr(type='smoke')
+ @test.idempotent_id('4773ebd5-ecbf-4255-b8d8-b63e6f72b65d')
def test_get_trusts_all(self):
self.create_trust()
trusts_get = self.client.get_trusts()
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 4f3ec05..8120fa7 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -19,9 +19,9 @@
class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('b537d090-afb9-4519-b95d-270b0708e87e')
def test_user_update(self):
# Test case to check if updating of user attributes is successful.
# Creating first user
@@ -65,6 +65,7 @@
self.assertEqual('false', str(new_user_get['enabled']).lower())
@test.attr(type='gate')
+ @test.idempotent_id('2d223a0e-e457-4a70-9fb1-febe027a0ff9')
def test_update_user_password(self):
# Creating User to check password updation
u_name = data_utils.rand_name('user')
@@ -86,6 +87,7 @@
self.assertEqual(token_details['user']['name'], u_name)
@test.attr(type='gate')
+ @test.idempotent_id('a831e70c-e35b-430b-92ed-81ebbc5437b8')
def test_list_user_projects(self):
# List the projects that a user has access upon
assigned_project_ids = list()
@@ -139,6 +141,7 @@
in missing_projects))
@test.attr(type='gate')
+ @test.idempotent_id('c10dcd90-461d-4b16-8e23-4eb836c00644')
def test_get_user(self):
# Get a user detail
self.data.setup_test_v3_user()
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 08bfd4f..ce54baa 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -13,12 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
-from tempest import auth
from tempest import clients
+from tempest.common import cred_provider
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
import tempest.test
@@ -29,10 +29,10 @@
class BaseIdentityAdminTest(tempest.test.BaseTestCase):
@classmethod
- def resource_setup(cls):
- super(BaseIdentityAdminTest, cls).resource_setup()
- cls.os_adm = clients.AdminManager(interface=cls._interface)
- cls.os = clients.Manager(interface=cls._interface)
+ def setup_credentials(cls):
+ super(BaseIdentityAdminTest, cls).setup_credentials()
+ cls.os_adm = clients.AdminManager()
+ cls.os = clients.Manager()
@classmethod
def disable_user(cls, user_name):
@@ -72,18 +72,27 @@
class BaseIdentityV2AdminTest(BaseIdentityAdminTest):
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(BaseIdentityV2AdminTest, cls).skip_checks()
if not CONF.identity_feature_enabled.api_v2:
raise cls.skipException("Identity api v2 is not enabled")
- super(BaseIdentityV2AdminTest, cls).resource_setup()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseIdentityV2AdminTest, cls).setup_clients()
cls.client = cls.os_adm.identity_client
cls.token_client = cls.os_adm.token_client
if not cls.client.has_admin_extensions():
raise cls.skipException("Admin extensions disabled")
- cls.data = DataGenerator(cls.client)
+
cls.non_admin_client = cls.os.identity_client
@classmethod
+ def resource_setup(cls):
+ super(BaseIdentityV2AdminTest, cls).resource_setup()
+ cls.data = DataGenerator(cls.client)
+
+ @classmethod
def resource_cleanup(cls):
cls.data.teardown_all()
super(BaseIdentityV2AdminTest, cls).resource_cleanup()
@@ -92,10 +101,14 @@
class BaseIdentityV3AdminTest(BaseIdentityAdminTest):
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(BaseIdentityV3AdminTest, cls).skip_checks()
if not CONF.identity_feature_enabled.api_v3:
raise cls.skipException("Identity api v3 is not enabled")
- super(BaseIdentityV3AdminTest, cls).resource_setup()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseIdentityV3AdminTest, cls).setup_clients()
cls.client = cls.os_adm.identity_v3_client
cls.token = cls.os_adm.token_v3_client
cls.endpoints_client = cls.os_adm.endpoints_client
@@ -149,11 +162,11 @@
@property
def test_credentials(self):
- return auth.get_credentials(username=self.test_user,
- user_id=self.user['id'],
- password=self.test_password,
- tenant_name=self.test_tenant,
- tenant_id=self.tenant['id'])
+ return cred_provider.get_credentials(username=self.test_user,
+ user_id=self.user['id'],
+ password=self.test_password,
+ tenant_name=self.test_tenant,
+ tenant_id=self.tenant['id'])
def setup_test_user(self):
"""Set up a test user."""
@@ -226,7 +239,7 @@
func(item['id'], **kwargs)
else:
func(item['id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
except Exception:
LOG.exception("Unexpected exception occurred in %s deletion."
diff --git a/tempest/api/identity/test_extension.py b/tempest/api/identity/test_extension.py
index e3badfc..f4a5c86 100644
--- a/tempest/api/identity/test_extension.py
+++ b/tempest/api/identity/test_extension.py
@@ -18,9 +18,9 @@
class ExtensionTestJSON(base.BaseIdentityV2AdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('85f3f661-f54c-4d48-b563-72ae952b9383')
def test_list_extensions(self):
# List all the extensions
body = self.non_admin_client.list_extensions()
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 12f3fdd..ffc3071 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -13,12 +13,12 @@
# under the License.
import cStringIO as StringIO
+from tempest_lib import exceptions as lib_exc
from tempest import clients
from tempest.common import credentials
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
import tempest.test
@@ -31,24 +31,31 @@
"""Base test class for Image API tests."""
@classmethod
+ def skip_checks(cls):
+ super(BaseImageTest, 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_credentials(cls):
+ super(BaseImageTest, cls).setup_credentials()
+ cls.isolated_creds = credentials.get_isolated_credentials(
+ cls.__name__, network_resources=cls.network_resources)
+ cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
+
+ @classmethod
def resource_setup(cls):
cls.set_network_resources()
super(BaseImageTest, cls).resource_setup()
cls.created_images = []
- cls._interface = 'json'
- cls.isolated_creds = credentials.get_isolated_credentials(
- cls.__name__, network_resources=cls.network_resources)
- if not CONF.service_available.glance:
- skip_msg = ("%s skipped as glance is not available" % cls.__name__)
- raise cls.skipException(skip_msg)
- cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
@classmethod
def resource_cleanup(cls):
for image_id in cls.created_images:
try:
cls.client.delete_image(image_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
for image_id in cls.created_images:
@@ -76,21 +83,33 @@
class BaseV1ImageTest(BaseImageTest):
@classmethod
- def resource_setup(cls):
- super(BaseV1ImageTest, cls).resource_setup()
- cls.client = cls.os.image_client
+ def skip_checks(cls):
+ super(BaseV1ImageTest, cls).skip_checks()
if not CONF.image_feature_enabled.api_v1:
msg = "Glance API v1 not supported"
raise cls.skipException(msg)
+ @classmethod
+ def setup_clients(cls):
+ super(BaseV1ImageTest, cls).setup_clients()
+ cls.client = cls.os.image_client
+
class BaseV1ImageMembersTest(BaseV1ImageTest):
+
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseV1ImageMembersTest, cls).setup_credentials()
+ cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseV1ImageMembersTest, cls).setup_clients()
+ cls.alt_img_cli = cls.os_alt.image_client
+
@classmethod
def resource_setup(cls):
super(BaseV1ImageMembersTest, cls).resource_setup()
- cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
-
- cls.alt_img_cli = cls.os_alt.image_client
cls.alt_tenant_id = cls.alt_img_cli.tenant_id
def _create_image(self):
@@ -106,23 +125,35 @@
class BaseV2ImageTest(BaseImageTest):
@classmethod
- def resource_setup(cls):
- super(BaseV2ImageTest, cls).resource_setup()
- cls.client = cls.os.image_client_v2
+ def skip_checks(cls):
+ super(BaseV2ImageTest, cls).skip_checks()
if not CONF.image_feature_enabled.api_v2:
msg = "Glance API v2 not supported"
raise cls.skipException(msg)
+ @classmethod
+ def setup_clients(cls):
+ super(BaseV2ImageTest, cls).setup_clients()
+ cls.client = cls.os.image_client_v2
+
class BaseV2MemberImageTest(BaseV2ImageTest):
@classmethod
- def resource_setup(cls):
- super(BaseV2MemberImageTest, cls).resource_setup()
+ def setup_credentials(cls):
+ super(BaseV2MemberImageTest, cls).setup_credentials()
creds = cls.isolated_creds.get_alt_creds()
cls.os_alt = clients.Manager(creds)
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseV2MemberImageTest, cls).setup_clients()
cls.os_img_client = cls.os.image_client_v2
cls.alt_img_client = cls.os_alt.image_client_v2
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseV2MemberImageTest, cls).resource_setup()
cls.alt_tenant_id = cls.alt_img_client.tenant_id
def _list_image_ids_as_alt(self):
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index d18a274..07a0df8 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -20,6 +20,7 @@
class ImageMembersTest(base.BaseV1ImageMembersTest):
@test.attr(type='gate')
+ @test.idempotent_id('1d6ef640-3a20-4c84-8710-d95828fdb6ad')
def test_add_image_member(self):
image = self._create_image()
self.client.add_member(self.alt_tenant_id, image)
@@ -31,6 +32,7 @@
self.alt_img_cli.get_image(image)
@test.attr(type='gate')
+ @test.idempotent_id('6a5328a5-80e8-4b82-bd32-6c061f128da9')
def test_get_shared_images(self):
image = self._create_image()
self.client.add_member(self.alt_tenant_id, image)
@@ -43,6 +45,7 @@
self.assertIn(image, images)
@test.attr(type='gate')
+ @test.idempotent_id('a76a3191-8948-4b44-a9d6-4053e5f2b138')
def test_remove_member(self):
image_id = self._create_image()
self.client.add_member(self.alt_tenant_id, image_id)
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
index aac63b4..c276d25 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -12,41 +12,45 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
from tempest.api.image import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ImageMembersNegativeTest(base.BaseV1ImageMembersTest):
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('147a9536-18e3-45da-91ea-b037a028f364')
def test_add_member_with_non_existing_image(self):
# Add member with non existing image.
non_exist_image = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.add_member,
+ self.assertRaises(lib_exc.NotFound, self.client.add_member,
self.alt_tenant_id, non_exist_image)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e1559f05-b667-4f1b-a7af-518b52dc0c0f')
def test_delete_member_with_non_existing_image(self):
# Delete member with non existing image.
non_exist_image = data_utils.rand_uuid()
- self.assertRaises(exceptions.NotFound, self.client.delete_member,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_member,
self.alt_tenant_id, non_exist_image)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f5720333-dd69-4194-bb76-d2f048addd56')
def test_delete_member_with_non_existing_tenant(self):
# Delete member with non existing tenant.
image_id = self._create_image()
non_exist_tenant = data_utils.rand_uuid_hex()
- self.assertRaises(exceptions.NotFound, self.client.delete_member,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_member,
non_exist_tenant, image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f25f89e4-0b6c-453b-a853-1f80b9d7ef26')
def test_get_image_without_membership(self):
# Image is hidden from another tenants.
image_id = self._create_image()
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.alt_img_cli.get_image,
image_id)
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index b9f12e6..a268128 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -27,6 +27,7 @@
"""Here we test the registration and creation of images."""
@test.attr(type='gate')
+ @test.idempotent_id('3027f8e6-3492-4a11-8575-c3293017af4d')
def test_register_then_upload(self):
# Register, then upload an image
properties = {'prop1': 'val1'}
@@ -50,6 +51,7 @@
self.assertEqual(1024, body.get('size'))
@test.attr(type='gate')
+ @test.idempotent_id('69da74d9-68a9-404b-9664-ff7164ccb0f5')
def test_register_remote_image(self):
# Register a new remote image
body = self.create_image(name='New Remote Image',
@@ -67,6 +69,7 @@
self.assertEqual(properties['key2'], 'value2')
@test.attr(type='gate')
+ @test.idempotent_id('6d0e13a7-515b-460c-b91f-9f4793f09816')
def test_register_http_image(self):
body = self.create_image(name='New Http Image',
container_format='bare',
@@ -80,6 +83,7 @@
self.client.get_image(image_id)
@test.attr(type='gate')
+ @test.idempotent_id('05b19d55-140c-40d0-b36b-fafd774d421b')
def test_register_image_with_min_ram(self):
# Register an image with min ram
properties = {'prop1': 'val1'}
@@ -166,6 +170,7 @@
return image_id
@test.attr(type='gate')
+ @test.idempotent_id('246178ab-3b33-4212-9a4b-a7fe8261794d')
def test_index_no_params(self):
# Simple test to see all fixture images returned
images_list = self.client.image_list()
@@ -174,6 +179,7 @@
self.assertIn(image_id, image_list)
@test.attr(type='gate')
+ @test.idempotent_id('f1755589-63d6-4468-b098-589820eb4031')
def test_index_disk_format(self):
images_list = self.client.image_list(disk_format='ami')
for image in images_list:
@@ -183,6 +189,7 @@
self.assertFalse(self.created_set - self.ami_set <= result_set)
@test.attr(type='gate')
+ @test.idempotent_id('2143655d-96d9-4bec-9188-8674206b4b3b')
def test_index_container_format(self):
images_list = self.client.image_list(container_format='bare')
for image in images_list:
@@ -192,6 +199,7 @@
self.assertFalse(self.created_set - self.bare_set <= result_set)
@test.attr(type='gate')
+ @test.idempotent_id('feb32ac6-22bb-4a16-afd8-9454bb714b14')
def test_index_max_size(self):
images_list = self.client.image_list(size_max=42)
for image in images_list:
@@ -201,6 +209,7 @@
self.assertFalse(self.created_set - self.size42_set <= result_set)
@test.attr(type='gate')
+ @test.idempotent_id('6ffc16d0-4cbf-4401-95c8-4ac63eac34d8')
def test_index_min_size(self):
images_list = self.client.image_list(size_min=142)
for image in images_list:
@@ -210,6 +219,7 @@
self.assertFalse(self.size42_set <= result_set)
@test.attr(type='gate')
+ @test.idempotent_id('e5dc26d9-9aa2-48dd-bda5-748e1445da98')
def test_index_status_active_detail(self):
images_list = self.client.image_list_detail(status='active',
sort_key='size',
@@ -222,6 +232,7 @@
self.assertEqual(image['status'], 'active')
@test.attr(type='gate')
+ @test.idempotent_id('097af10a-bae8-4342-bff4-edf89969ed2a')
def test_index_name(self):
images_list = self.client.image_list_detail(
name='New Remote Image dup')
@@ -256,6 +267,7 @@
return image_id
@test.attr(type='gate')
+ @test.idempotent_id('01752c1c-0275-4de3-9e5b-876e44541928')
def test_list_image_metadata(self):
# All metadata key/value pairs for an image should be returned
resp_metadata = self.client.get_image_meta(self.image_id)
@@ -263,6 +275,7 @@
self.assertEqual(expected, resp_metadata['properties'])
@test.attr(type='gate')
+ @test.idempotent_id('d6d7649c-08ce-440d-9ea7-e3dda552f33c')
def test_update_image_metadata(self):
# The metadata for the image should match the updated values
req_metadata = {'key1': 'alt1', 'key2': 'value2'}
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index 66556e0..85b9435 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.image import base
-from tempest import exceptions
from tempest import test
@@ -22,49 +23,57 @@
"""Here are negative tests for the deletion and creation of images."""
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('036ede36-6160-4463-8c01-c781eee6369d')
def test_register_with_invalid_container_format(self):
# Negative tests for invalid data supplied to POST /images
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
'test', 'wrong', 'vhd')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
def test_register_with_invalid_disk_format(self):
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
'test', 'bare', 'wrong')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bb016f15-0820-4f27-a92d-09b2f67d2488')
def test_delete_image_with_invalid_image_id(self):
# An image should not be deleted with invalid image id
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
'!@$%^&*()')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ec652588-7e3c-4b67-a2f2-0fa96f57c8fc')
def test_delete_non_existent_image(self):
# Return an error while trying to delete a non-existent image
non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
non_existent_image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('04f72aa3-fcec-45a3-81a3-308ef7cc82bc')
def test_delete_image_blank_id(self):
# Return an error while trying to delete an image with blank Id
- self.assertRaises(exceptions.NotFound, self.client.delete_image, '')
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('950e5054-a3c7-4dee-ada5-e576f1087abd')
def test_delete_image_non_hex_string_id(self):
# Return an error while trying to delete an image with non hex id
image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4ed757cd-450c-44b1-9fd1-c819748c650d')
def test_delete_image_negative_image_id(self):
# Return an error while trying to delete an image with negative id
- self.assertRaises(exceptions.NotFound, self.client.delete_image, -1)
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image, -1)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('a4a448ab-3db2-4d2d-b9b2-6a1271241dfe')
def test_delete_image_id_is_over_35_character_limit(self):
# Return an error while trying to delete image with id over limit
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
'11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index e307c5c..a4f5ae3 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -28,6 +28,7 @@
"""
@test.attr(type='gate')
+ @test.idempotent_id('139b765e-7f3d-4b3d-8b37-3ca3876ee318')
def test_register_upload_get_image_file(self):
"""
@@ -65,10 +66,11 @@
self.assertEqual(1024, body.get('size'))
# Now try get image file
- _, body = self.client.get_image_file(image_id)
- self.assertEqual(file_content, body)
+ body = self.client.get_image_file(image_id)
+ self.assertEqual(file_content, body.data)
@test.attr(type='gate')
+ @test.idempotent_id('f848bb94-1c6e-45a4-8726-39e3a5b23535')
def test_delete_image(self):
# Deletes an image by image_id
@@ -90,6 +92,7 @@
self.assertNotIn(image_id, images_id)
@test.attr(type='gate')
+ @test.idempotent_id('f66891a7-a35c-41a8-b590-a065c2a1caa6')
def test_update_image(self):
# Updates an image by image_id
@@ -168,6 +171,7 @@
self.assertEqual(params[key], image[key], msg)
@test.attr(type='gate')
+ @test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
def test_index_no_params(self):
# Simple test to see all fixture images returned
images_list = self.client.image_list()
@@ -177,24 +181,28 @@
self.assertIn(image, image_list)
@test.attr(type='gate')
+ @test.idempotent_id('9959ca1d-1aa7-4b7a-a1ea-0fff0499b37e')
def test_list_images_param_container_format(self):
# Test to get all images with container_format='bare'
params = {"container_format": "bare"}
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('4a4735a7-f22f-49b6-b0d9-66e1ef7453eb')
def test_list_images_param_disk_format(self):
# Test to get all images with disk_format = raw
params = {"disk_format": "raw"}
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('7a95bb92-d99e-4b12-9718-7bc6ab73e6d2')
def test_list_images_param_visibility(self):
# Test to get all images with visibility = private
params = {"visibility": "private"}
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('cf1b9a48-8340-480e-af7b-fe7e17690876')
def test_list_images_param_size(self):
# Test to get all images by size
image_id = self.created_images[1]
@@ -205,6 +213,7 @@
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('4ad8c157-971a-4ba8-aa84-ed61154b1e7f')
def test_list_images_param_min_max_size(self):
# Test to get all images with size between 2000 to 3000
image_id = self.created_images[1]
@@ -222,12 +231,14 @@
"Failed to get images by size_min and size_max")
@test.attr(type='gate')
+ @test.idempotent_id('7fc9e369-0f58-4d05-9aa5-0969e2d59d15')
def test_list_images_param_status(self):
# Test to get all active images
params = {"status": "active"}
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('e914a891-3cc8-4b40-ad32-e0a39ffbddbb')
def test_list_images_param_limit(self):
# Test to get images by limit
params = {"limit": 2}
@@ -237,6 +248,7 @@
"Failed to get images by limit")
@test.attr(type='gate')
+ @test.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
def test_get_image_schema(self):
# Test to get image schema
schema = "image"
@@ -244,6 +256,7 @@
self.assertEqual("image", body['name'])
@test.attr(type='gate')
+ @test.idempotent_id('25c8d7b2-df21-460f-87ac-93130bcdc684')
def test_get_images_schema(self):
# Test to get images schema
schema = "images"
diff --git a/tempest/api/image/v2/test_images_member.py b/tempest/api/image/v2/test_images_member.py
index ec1cf14..bbe4ce8 100644
--- a/tempest/api/image/v2/test_images_member.py
+++ b/tempest/api/image/v2/test_images_member.py
@@ -15,9 +15,9 @@
class ImagesMemberTest(base.BaseV2MemberImageTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('5934c6ea-27dc-4d6e-9421-eeb5e045494a')
def test_image_share_accept(self):
image_id = self._create_image()
member = self.os_img_client.add_member(image_id,
@@ -39,6 +39,7 @@
self.assertEqual(member['status'], 'accepted')
@test.attr(type='gate')
+ @test.idempotent_id('d9e83e5f-3524-4b38-a900-22abcb26e90e')
def test_image_share_reject(self):
image_id = self._create_image()
member = self.os_img_client.add_member(image_id,
@@ -53,6 +54,7 @@
self.assertNotIn(image_id, self._list_image_ids_as_alt())
@test.attr(type='gate')
+ @test.idempotent_id('a6ee18b9-4378-465e-9ad9-9a6de58a3287')
def test_get_image_member(self):
image_id = self._create_image()
self.os_img_client.add_member(image_id,
@@ -69,6 +71,7 @@
self.assertEqual('accepted', member['status'])
@test.attr(type='gate')
+ @test.idempotent_id('72989bc7-2268-48ed-af22-8821e835c914')
def test_remove_image_member(self):
image_id = self._create_image()
self.os_img_client.add_member(image_id,
@@ -82,11 +85,13 @@
self.assertNotIn(image_id, self._list_image_ids_as_alt())
@test.attr(type='gate')
+ @test.idempotent_id('634dcc3f-f6e2-4409-b8fd-354a0bb25d83')
def test_get_image_member_schema(self):
body = self.os_img_client.get_schema("member")
self.assertEqual("member", body['name'])
@test.attr(type='gate')
+ @test.idempotent_id('6ae916ef-1052-4e11-8d36-b3ae14853cbb')
def test_get_image_members_schema(self):
body = self.os_img_client.get_schema("members")
self.assertEqual("members", body['name'])
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index 1f8e3d0..a0c59ff 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -10,32 +10,34 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.image import base
-from tempest import exceptions
from tempest import test
class ImagesMemberNegativeTest(base.BaseV2MemberImageTest):
- _interface = 'json'
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
def test_image_share_invalid_status(self):
image_id = self._create_image()
member = self.os_img_client.add_member(image_id,
self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.alt_img_client.update_member_status,
image_id, self.alt_tenant_id, 'notavalidstatus')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
def test_image_share_owner_cannot_accept(self):
image_id = self._create_image()
member = self.os_img_client.add_member(image_id,
self.alt_tenant_id)
self.assertEqual(member['status'], 'pending')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.os_img_client.update_member_status,
image_id, self.alt_tenant_id, 'accepted')
self.assertNotIn(image_id, self._list_image_ids_as_alt())
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index fc781b1..23d32f4 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -16,8 +16,9 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.image import base
-from tempest import exceptions
from tempest import test
@@ -36,19 +37,22 @@
"""
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81d9f')
def test_get_non_existent_image(self):
# get the non-existent image
non_existent_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound, self.client.get_image,
+ self.assertRaises(lib_exc.NotFound, self.client.get_image,
non_existent_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2562ad')
def test_get_image_null_id(self):
# get image with image_id = NULL
image_id = ""
- self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+ self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e57fc127-7ba0-4693-92d7-1d8a05ebcba9')
def test_get_delete_deleted_image(self):
# get and delete the deleted image
# create and delete image
@@ -60,33 +64,37 @@
self.client.wait_for_resource_deletion(image_id)
# get the deleted image
- self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
+ self.assertRaises(lib_exc.NotFound, self.client.get_image, image_id)
# delete the deleted image
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('6fe40f1c-57bd-4918-89cc-8500f850f3de')
def test_delete_non_existing_image(self):
# delete non-existent image
non_existent_image_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
non_existent_image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('32248db1-ab88-4821-9604-c7c369f1f88c')
def test_delete_image_null_id(self):
# delete image with image_id=NULL
image_id = ""
- self.assertRaises(exceptions.NotFound, self.client.delete_image,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image,
image_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('292bd310-369b-41c7-a7a3-10276ef76753')
def test_register_with_invalid_container_format(self):
# Negative tests for invalid data supplied to POST /images
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
'test', 'wrong', 'vhd')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('70c6040c-5a97-4111-9e13-e73665264ce1')
def test_register_with_invalid_disk_format(self):
- self.assertRaises(exceptions.BadRequest, self.client.create_image,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_image,
'test', 'bare', 'wrong')
diff --git a/tempest/api/image/v2/test_images_tags.py b/tempest/api/image/v2/test_images_tags.py
index 4686de2..350ede3 100644
--- a/tempest/api/image/v2/test_images_tags.py
+++ b/tempest/api/image/v2/test_images_tags.py
@@ -20,6 +20,7 @@
class ImagesTagsTest(base.BaseV2ImageTest):
@test.attr(type='gate')
+ @test.idempotent_id('10407036-6059-4f95-a2cd-cbbbee7ed329')
def test_update_delete_tags_for_image(self):
body = self.create_image(container_format='bare',
disk_format='raw',
diff --git a/tempest/api/image/v2/test_images_tags_negative.py b/tempest/api/image/v2/test_images_tags_negative.py
index aa0a214..bbe0431 100644
--- a/tempest/api/image/v2/test_images_tags_negative.py
+++ b/tempest/api/image/v2/test_images_tags_negative.py
@@ -14,23 +14,26 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.image import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ImagesTagsNegativeTest(base.BaseV2ImageTest):
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8cd30f82-6f9a-4c6e-8034-c1b51fba43d9')
def test_update_tags_for_non_existing_image(self):
# Update tag with non existing image.
tag = data_utils.rand_name('tag-')
non_exist_image = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound, self.client.add_image_tag,
+ self.assertRaises(lib_exc.NotFound, self.client.add_image_tag,
non_exist_image, tag)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('39c023a2-325a-433a-9eea-649bf1414b19')
def test_delete_non_existing_tag(self):
# Delete non existing tag.
body = self.create_image(container_format='bare',
@@ -40,5 +43,5 @@
image_id = body['id']
tag = data_utils.rand_name('non-exist-tag-')
self.addCleanup(self.client.delete_image, image_id)
- self.assertRaises(exceptions.NotFound, self.client.delete_image_tag,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_image_tag,
image_id, tag)
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 58511a9..eae0707 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -35,13 +35,25 @@
"""
@classmethod
- def resource_setup(cls):
- super(BaseMessagingTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(BaseMessagingTest, cls).skip_checks()
if not CONF.service_available.zaqar:
raise cls.skipException("Zaqar support is required")
- os = cls.get_client_manager()
+
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseMessagingTest, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseMessagingTest, cls).setup_clients()
+ cls.client = cls.os.messaging_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseMessagingTest, cls).resource_setup()
cls.messaging_cfg = CONF.messaging
- cls.client = os.messaging_client
@classmethod
def create_queue(cls, queue_name):
diff --git a/tempest/api/messaging/test_claims.py b/tempest/api/messaging/test_claims.py
index 1aab8d2..ebaa283 100644
--- a/tempest/api/messaging/test_claims.py
+++ b/tempest/api/messaging/test_claims.py
@@ -29,7 +29,6 @@
class TestClaims(base.BaseMessagingTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -56,6 +55,7 @@
return resp, body
@test.attr(type='smoke')
+ @test.idempotent_id('936cb1ca-b7af-44dd-a752-805e8c98156f')
def test_post_claim(self):
_, body = self._post_and_claim_messages(queue_name=self.queue_name)
claimed_message_uri = body[0]['href']
@@ -69,6 +69,7 @@
@decorators.skip_because(bug="1331517")
@test.attr(type='smoke')
+ @test.idempotent_id('84e491f4-68c6-451f-9846-b8f868eb27c5')
def test_query_claim(self):
# Post a Claim
resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
@@ -83,6 +84,7 @@
@decorators.skip_because(bug="1328111")
@test.attr(type='smoke')
+ @test.idempotent_id('420ef0c5-9bd6-4b82-b06d-d9da330fefd3')
def test_update_claim(self):
# Post a Claim
resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
@@ -106,6 +108,7 @@
self.client.delete_messages(claimed_message_uri)
@test.attr(type='smoke')
+ @test.idempotent_id('fd4c7921-cb3f-4ed8-9ac8-e8f1e74c44aa')
def test_release_claim(self):
# Post a Claim
resp, body = self._post_and_claim_messages(queue_name=self.queue_name)
diff --git a/tempest/api/messaging/test_messages.py b/tempest/api/messaging/test_messages.py
index 3c27ac2..12a3df5 100644
--- a/tempest/api/messaging/test_messages.py
+++ b/tempest/api/messaging/test_messages.py
@@ -26,7 +26,6 @@
class TestMessages(base.BaseMessagingTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -42,6 +41,7 @@
return resp, body
@test.attr(type='smoke')
+ @test.idempotent_id('93867172-a414-4eb3-a639-96e943c516b4')
def test_post_messages(self):
# Post Messages
resp, _ = self._post_messages()
@@ -54,6 +54,7 @@
self.assertEqual('200', resp['status'])
@test.attr(type='smoke')
+ @test.idempotent_id('c967d59a-e919-41cb-994b-1c4300452c80')
def test_list_messages(self):
# Post Messages
self._post_messages()
@@ -65,6 +66,7 @@
self.assertEqual('200', resp['status'])
@test.attr(type='smoke')
+ @test.idempotent_id('2a68e3de-24df-47c3-9039-ec4156656bf8')
def test_get_message(self):
# Post Messages
_, body = self._post_messages()
@@ -77,6 +79,7 @@
self.assertEqual('200', resp['status'])
@test.attr(type='smoke')
+ @test.idempotent_id('c4b0a30b-efda-4b87-a395-0c43140df74d')
def test_get_multiple_messages(self):
# Post Messages
resp, _ = self._post_messages()
@@ -89,6 +92,7 @@
self.assertEqual('200', resp['status'])
@test.attr(type='smoke')
+ @test.idempotent_id('fc0fca47-dd8b-4ecc-8522-d9c191f9bc9f')
def test_delete_single_message(self):
# Post Messages
_, body = self._post_messages()
@@ -104,6 +108,7 @@
self.assertEqual('204', resp['status'])
@test.attr(type='smoke')
+ @test.idempotent_id('00cca069-5c8f-4b42-bff1-c577da2a4546')
def test_delete_multiple_messages(self):
# Post Messages
resp, _ = self._post_messages()
diff --git a/tempest/api/messaging/test_queues.py b/tempest/api/messaging/test_queues.py
index accbd17..5d9a7c7 100644
--- a/tempest/api/messaging/test_queues.py
+++ b/tempest/api/messaging/test_queues.py
@@ -16,11 +16,11 @@
import logging
from six import moves
+from tempest_lib import exceptions as lib_exc
from testtools import matchers
from tempest.api.messaging import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -30,6 +30,7 @@
class TestQueues(base.BaseMessagingTest):
@test.attr(type='smoke')
+ @test.idempotent_id('9f1c4c72-80c5-4dac-acf3-188cef42e36c')
def test_create_delete_queue(self):
# Create & Delete Queue
queue_name = data_utils.rand_name('test-')
@@ -42,13 +43,12 @@
self.assertEqual('', body)
self.delete_queue(queue_name)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.get_queue,
queue_name)
class TestManageQueue(base.BaseMessagingTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -61,18 +61,21 @@
cls.client.create_queue(queue_name)
@test.attr(type='smoke')
+ @test.idempotent_id('ccd3d69e-f156-4c5f-8a12-b4f24bee44e1')
def test_check_queue_existence(self):
# Checking Queue Existence
for queue_name in self.queues:
self.check_queue_exists(queue_name)
@test.attr(type='smoke')
+ @test.idempotent_id('e27634d8-9c8f-47d8-a677-655c47658d3e')
def test_check_queue_head(self):
# Checking Queue Existence by calling HEAD
for queue_name in self.queues:
self.check_queue_exists_head(queue_name)
@test.attr(type='smoke')
+ @test.idempotent_id('0a0feeca-7768-4303-806d-82bbbb796ad3')
def test_list_queues(self):
# Listing queues
_, body = self.list_queues()
@@ -81,6 +84,7 @@
self.assertIn(item['name'], self.queues)
@test.attr(type='smoke')
+ @test.idempotent_id('8fb66602-077d-49d6-ae1a-5f2091739178')
def test_get_queue_stats(self):
# Retrieve random queue
queue_name = self.queues[data_utils.rand_int_id(0,
@@ -94,6 +98,7 @@
self.assertNotIn(element, msgs)
@test.attr(type='smoke')
+ @test.idempotent_id('0e2441e6-6593-4bdb-a3c0-20e66eeb3fff')
def test_set_and_get_queue_metadata(self):
# Retrieve random queue
queue_name = self.queues[data_utils.rand_int_id(0,
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index e7fd016..d5454ec 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -18,7 +18,6 @@
class AgentManagementTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -31,6 +30,7 @@
cls.agent = agents[0]
@test.attr(type='smoke')
+ @test.idempotent_id('9c80f04d-11f3-44a4-8738-ed2f879b0ff4')
def test_list_agent(self):
body = self.admin_client.list_agents()
agents = body['agents']
@@ -43,17 +43,20 @@
self.assertIn(self.agent, agents)
@test.attr(type=['smoke'])
+ @test.idempotent_id('e335be47-b9a1-46fd-be30-0874c0b751e6')
def test_list_agents_non_admin(self):
body = self.client.list_agents()
self.assertEqual(len(body["agents"]), 0)
@test.attr(type='smoke')
+ @test.idempotent_id('869bc8e8-0fda-4a30-9b71-f8a7cf58ca9f')
def test_show_agent(self):
body = self.admin_client.show_agent(self.agent['id'])
agent = body['agent']
self.assertEqual(agent['id'], self.agent['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('371dfc5b-55b9-4cb5-ac82-c40eadaac941')
def test_update_agent_status(self):
origin_status = self.agent['admin_state_up']
# Try to update the 'admin_state_up' to the original
@@ -65,6 +68,7 @@
self.assertEqual(origin_status, updated_status)
@test.attr(type='smoke')
+ @test.idempotent_id('68a94a14-1243-46e6-83bf-157627e31556')
def test_update_agent_description(self):
self.useFixture(fixtures.LockFixture('agent_description'))
description = 'description for update agent.'
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index a89f25c..26f5e7a 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -17,7 +17,6 @@
class DHCPAgentSchedulersTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -33,11 +32,13 @@
cls.port = cls.create_port(cls.network)
@test.attr(type='smoke')
+ @test.idempotent_id('5032b1fe-eb42-4a64-8f3b-6e189d8b5c7d')
def test_list_dhcp_agent_hosting_network(self):
self.admin_client.list_dhcp_agent_hosting_network(
self.network['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('30c48f98-e45d-4ffb-841c-b8aad57c7587')
def test_list_networks_hosted_by_one_dhcp(self):
body = self.admin_client.list_dhcp_agent_hosting_network(
self.network['id'])
@@ -57,6 +58,7 @@
return network_id in network_ids
@test.attr(type='smoke')
+ @test.idempotent_id('a0856713-6549-470c-a656-e97c8df9a14d')
def test_add_remove_network_from_dhcp_agent(self):
# The agent is now bound to the network, we can free the port
self.client.delete_port(self.port['id'])
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 3110aab..d942641 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -12,10 +12,10 @@
from tempest.api.network import base
from tempest.common.utils import data_utils
+from tempest import test
class ExternalNetworksTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -31,6 +31,7 @@
self.addCleanup(self.admin_client.delete_network, network['id'])
return network
+ @test.idempotent_id('462be770-b310-4df9-9c42-773217e4c8b1')
def test_create_external_network(self):
# Create a network as an admin user specifying the
# external network extension attribute
@@ -39,6 +40,7 @@
self.assertIsNotNone(ext_network['id'])
self.assertTrue(ext_network['router:external'])
+ @test.idempotent_id('4db5417a-e11c-474d-a361-af00ebef57c5')
def test_update_external_network(self):
# Update a network as an admin user specifying the
# external network extension attribute
@@ -51,6 +53,7 @@
# Verify that router:external parameter was updated
self.assertTrue(updated_network['router:external'])
+ @test.idempotent_id('39be4c9b-a57e-4ff9-b7c7-b218e209dfcc')
def test_list_external_networks(self):
# Create external_net
external_network = self._create_network()
@@ -67,6 +70,7 @@
elif net['id'] == external_network['id']:
self.assertTrue(net['router:external'])
+ @test.idempotent_id('2ac50ab2-7ebd-4e27-b3ce-a9e399faaea2')
def test_show_external_networks_attribute(self):
# Create external_net
external_network = self._create_network()
@@ -84,6 +88,7 @@
self.assertEqual(self.network['id'], show_net['id'])
self.assertFalse(show_net['router:external'])
+ @test.idempotent_id('82068503-2cf2-4ed4-b3be-ecb89432e4bb')
def test_delete_external_networks_with_floating_ip(self):
"""Verifies external network can be deleted while still holding
(unassociated) floating IPs
diff --git a/tempest/api/network/admin/test_external_networks_negative.py b/tempest/api/network/admin/test_external_networks_negative.py
index 7dbb347..c2fa0dd 100644
--- a/tempest/api/network/admin/test_external_networks_negative.py
+++ b/tempest/api/network/admin/test_external_networks_negative.py
@@ -13,18 +13,19 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class ExternalNetworksAdminNegativeTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
@test.attr(type=['negative'])
+ @test.idempotent_id('d402ae6c-0be0-4d8e-833b-a738895d98d0')
def test_create_port_with_precreated_floatingip_as_fixed_ip(self):
"""
External networks can be used to create both floating-ip as well
@@ -47,7 +48,7 @@
fixed_ips = [{'ip_address': floating_ip_address}]
# create a port which will internally create an instance-ip
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
client.create_port,
network_id=CONF.network.public_network_id,
fixed_ips=fixed_ips)
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index 62ba1b3..a3a9977 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -15,6 +15,7 @@
from tempest.api.network import base
from tempest import clients
+from tempest.common.utils import data_utils
from tempest import config
from tempest import test
@@ -22,7 +23,7 @@
class FloatingIPAdminTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
+
force_tenant_isolation = True
@classmethod
@@ -32,8 +33,15 @@
cls.floating_ip = cls.create_floatingip(cls.ext_net_id)
cls.alt_manager = clients.Manager(cls.isolated_creds.get_alt_creds())
cls.alt_client = cls.alt_manager.network_client
+ cls.network = cls.create_network()
+ cls.subnet = cls.create_subnet(cls.network)
+ cls.router = cls.create_router(data_utils.rand_name('router-'),
+ external_network_id=cls.ext_net_id)
+ cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+ cls.port = cls.create_port(cls.network)
@test.attr(type='smoke')
+ @test.idempotent_id('64f2100b-5471-4ded-b46c-ddeeeb4f231b')
def test_list_floating_ips_from_admin_and_nonadmin(self):
# Create floating ip from admin user
floating_ip_admin = self.admin_client.create_floatingip(
@@ -63,3 +71,40 @@
self.assertNotIn(floating_ip_admin['floatingip']['id'],
floating_ip_ids)
self.assertNotIn(floating_ip_alt['id'], floating_ip_ids)
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('32727cc3-abe2-4485-a16e-48f2d54c14f2')
+ def test_create_list_show_floating_ip_with_tenant_id_by_admin(self):
+ # Creates a floating IP
+ body = self.admin_client.create_floatingip(
+ floating_network_id=self.ext_net_id,
+ tenant_id=self.network['tenant_id'],
+ port_id=self.port['id'])
+ created_floating_ip = body['floatingip']
+ self.addCleanup(self.client.delete_floatingip,
+ created_floating_ip['id'])
+ self.assertIsNotNone(created_floating_ip['id'])
+ self.assertIsNotNone(created_floating_ip['tenant_id'])
+ self.assertIsNotNone(created_floating_ip['floating_ip_address'])
+ self.assertEqual(created_floating_ip['port_id'], self.port['id'])
+ self.assertEqual(created_floating_ip['floating_network_id'],
+ self.ext_net_id)
+ port = self.port['fixed_ips']
+ self.assertEqual(created_floating_ip['fixed_ip_address'],
+ port[0]['ip_address'])
+ # Verifies the details of a floating_ip
+ floating_ip = self.admin_client.show_floatingip(
+ created_floating_ip['id'])
+ shown_floating_ip = floating_ip['floatingip']
+ self.assertEqual(shown_floating_ip['id'], created_floating_ip['id'])
+ self.assertEqual(shown_floating_ip['floating_network_id'],
+ self.ext_net_id)
+ self.assertEqual(shown_floating_ip['tenant_id'],
+ self.network['tenant_id'])
+ self.assertEqual(shown_floating_ip['floating_ip_address'],
+ created_floating_ip['floating_ip_address'])
+ self.assertEqual(shown_floating_ip['port_id'], self.port['id'])
+ # Verify the floating ip exists in the list of all floating_ips
+ floating_ips = self.admin_client.list_floatingips()
+ floatingip_id_list = [f['id'] for f in floating_ips['floatingips']]
+ self.assertIn(created_floating_ip['id'], floatingip_id_list)
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index a6de581..e6fa0a6 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -18,7 +18,6 @@
class L3AgentSchedulerTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -51,10 +50,12 @@
raise cls.skipException(msg)
@test.attr(type='smoke')
+ @test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
def test_list_routers_on_l3_agent(self):
self.admin_client.list_routers_on_l3_agent(self.agent['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('9464e5e7-8625-49c3-8fd1-89c52be59d66')
def test_add_list_remove_router_on_l3_agent(self):
l3_agent_ids = list()
name = data_utils.rand_name('router1-')
diff --git a/tempest/api/network/admin/test_lbaas_agent_scheduler.py b/tempest/api/network/admin/test_lbaas_agent_scheduler.py
index da1af36..c178fc0 100644
--- a/tempest/api/network/admin/test_lbaas_agent_scheduler.py
+++ b/tempest/api/network/admin/test_lbaas_agent_scheduler.py
@@ -18,7 +18,6 @@
class LBaaSAgentSchedulerTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -47,6 +46,7 @@
"HTTP", cls.subnet)
@test.attr(type='smoke')
+ @test.idempotent_id('e5ea8b15-4f44-4350-963c-e0fcb533ee79')
def test_list_pools_on_lbaas_agent(self):
found = False
body = self.admin_client.list_agents(
@@ -65,6 +65,7 @@
self.assertTrue(found, msg)
@test.attr(type='smoke')
+ @test.idempotent_id('e2745593-fd79-4b98-a262-575fd7865796')
def test_show_lbaas_agent_hosting_pool(self):
body = self.admin_client.show_lbaas_agent_hosting_pool(
self.pool['id'])
diff --git a/tempest/api/network/admin/test_load_balancer_admin_actions.py b/tempest/api/network/admin/test_load_balancer_admin_actions.py
index e81616b..931f079 100644
--- a/tempest/api/network/admin/test_load_balancer_admin_actions.py
+++ b/tempest/api/network/admin/test_load_balancer_admin_actions.py
@@ -19,7 +19,6 @@
class LoadBalancerAdminTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Test admin actions for load balancer.
@@ -44,6 +43,7 @@
"ROUND_ROBIN", "HTTP", cls.subnet)
@test.attr(type='smoke')
+ @test.idempotent_id('6b0a20d8-4fcd-455e-b54f-ec4db5199518')
def test_create_vip_as_admin_for_another_tenant(self):
name = data_utils.rand_name('vip-')
body = self.admin_client.create_pool(
@@ -70,6 +70,7 @@
self.assertEqual(vip['name'], show_vip['name'])
@test.attr(type='smoke')
+ @test.idempotent_id('74552cfc-ab78-4fb6-825b-f67bca379921')
def test_create_health_monitor_as_admin_for_another_tenant(self):
body = (
self.admin_client.create_health_monitor(delay=4,
@@ -87,6 +88,7 @@
self.assertEqual(health_monitor['id'], show_health_monitor['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('266a192d-3c22-46c4-a8fb-802450301e82')
def test_create_pool_from_admin_user_other_tenant(self):
body = self.admin_client.create_pool(
name=data_utils.rand_name('pool-'),
@@ -100,6 +102,7 @@
self.assertEqual(self.tenant_id, pool['tenant_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('158bb272-b9ed-4cfc-803c-661dac46f783')
def test_create_member_from_admin_user_other_tenant(self):
body = self.admin_client.create_member(address="10.0.9.47",
protocol_port=80,
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index f8dfca9..1ea24fe 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -20,7 +20,6 @@
class QuotasTest(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -84,10 +83,12 @@
self.assertNotEqual(tenant_id, q['tenant_id'])
@test.attr(type='gate')
+ @test.idempotent_id('2390f766-836d-40ef-9aeb-e810d78207fb')
def test_quotas(self):
new_quotas = {'network': 0, 'security_group': 0}
self._check_quotas(new_quotas)
+ @test.idempotent_id('a7add2b1-691e-44d6-875f-697d9685f091')
@test.requires_ext(extension='lbaas', service='network')
@test.attr(type='gate')
def test_lbaas_quotas(self):
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
new file mode 100644
index 0000000..d1833dd
--- /dev/null
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -0,0 +1,101 @@
+# Copyright 2015 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.network import base_routers as base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class RoutersTestDVR(base.BaseRouterTest):
+
+ @classmethod
+ def resource_setup(cls):
+ for ext in ['router', 'dvr']:
+ if not test.is_extension_enabled(ext, 'network'):
+ msg = "%s extension not enabled." % ext
+ raise cls.skipException(msg)
+ # The check above will pass if api_extensions=all, which does
+ # not mean DVR extension itself is present.
+ # Instead, we have to check whether DVR is actually present by using
+ # admin credentials to create router with distributed=True attribute
+ # and checking for BadRequest exception and that the resulting router
+ # has a distributed attribute.
+ super(RoutersTestDVR, cls).resource_setup()
+ name = data_utils.rand_name('pretest-check')
+ router = cls.admin_client.create_router(name)
+ if 'distributed' not in router['router']:
+ msg = "'distributed' attribute not found. DVR Possibly not enabled"
+ raise cls.skipException(msg)
+ cls.admin_client.delete_router(router['router']['id'])
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('08a2a0a8-f1e4-4b34-8e30-e522e836c44e')
+ def test_distributed_router_creation(self):
+ """
+ Test uses administrative credentials to creates a
+ DVR (Distributed Virtual Routing) router using the
+ distributed=True.
+
+ Acceptance
+ The router is created and the "distributed" attribute is
+ set to True
+ """
+ name = data_utils.rand_name('router')
+ router = self.admin_client.create_router(name, distributed=True)
+ self.addCleanup(self.admin_client.delete_router,
+ router['router']['id'])
+ self.assertTrue(router['router']['distributed'])
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('8a0a72b4-7290-4677-afeb-b4ffe37bc352')
+ def test_centralized_router_creation(self):
+ """
+ Test uses administrative credentials to creates a
+ CVR (Centralized Virtual Routing) router using the
+ distributed=False.
+
+ Acceptance
+ The router is created and the "distributed" attribute is
+ set to False, thus making it a "Centralized Virtual Router"
+ as opposed to a "Distributed Virtual Router"
+ """
+ name = data_utils.rand_name('router')
+ router = self.admin_client.create_router(name, distributed=False)
+ self.addCleanup(self.admin_client.delete_router,
+ router['router']['id'])
+ self.assertFalse(router['router']['distributed'])
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('acd43596-c1fb-439d-ada8-31ad48ae3c2e')
+ def test_centralized_router_update_to_dvr(self):
+ """
+ Test uses administrative credentials to creates a
+ CVR (Centralized Virtual Routing) router using the
+ distributed=False.Then it will "update" the router
+ distributed attribute to True
+
+ Acceptance
+ The router is created and the "distributed" attribute is
+ set to False. Once the router is updated, the distributed
+ attribute will be set to True
+ """
+ name = data_utils.rand_name('router')
+ router = self.admin_client.create_router(name, distributed=False)
+ self.addCleanup(self.admin_client.delete_router,
+ router['router']['id'])
+ self.assertFalse(router['router']['distributed'])
+ router = self.admin_client.update_router(router['router']['id'],
+ distributed=True)
+ self.assertTrue(router['router']['distributed'])
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 10cda53..e8c8de3 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -14,6 +14,7 @@
# under the License.
import netaddr
+from tempest_lib import exceptions as lib_exc
from tempest import clients
from tempest.common.utils import data_utils
@@ -49,7 +50,6 @@
neutron as True
"""
- _interface = 'json'
force_tenant_isolation = False
# Default to ipv4.
@@ -177,7 +177,7 @@
try:
delete_callable(*args, **kwargs)
# if resource is not found, this means it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@classmethod
@@ -223,7 +223,7 @@
gateway_ip=gateway_ip,
**kwargs)
break
- except exceptions.BadRequest as e:
+ except lib_exc.BadRequest as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
if not is_overlapping_cidr:
raise
@@ -399,7 +399,7 @@
try:
cls.client.remove_router_interface_with_subnet_id(
router['id'], i['fixed_ips'][0]['subnet_id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
cls.client.delete_router(router['id'])
@@ -420,8 +420,7 @@
try:
creds = cls.isolated_creds.get_admin_creds()
- cls.os_adm = clients.Manager(
- credentials=creds, interface=cls._interface)
+ cls.os_adm = clients.Manager(credentials=creds)
except NotImplementedError:
msg = ("Missing Administrative Network API credentials "
"in configuration.")
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index 57887ac..99bd82c 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -23,7 +23,6 @@
class AllowedAddressPairTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the Neutron Allowed Address Pair API extension using the Tempest
@@ -54,6 +53,7 @@
cls.mac_address = port['mac_address']
@test.attr(type='smoke')
+ @test.idempotent_id('86c3529b-1231-40de-803c-00e40882f043')
def test_create_list_port_with_address_pair(self):
# Create port with allowed address pair attribute
allowed_address_pairs = [{'ip_address': self.ip_address,
@@ -92,17 +92,20 @@
self.assertEqual(allowed_address_pair, allowed_address_pairs)
@test.attr(type='smoke')
+ @test.idempotent_id('9599b337-272c-47fd-b3cf-509414414ac4')
def test_update_port_with_address_pair(self):
# Update port with allowed address pair
self._update_port_with_address(self.ip_address)
@test.attr(type='smoke')
+ @test.idempotent_id('4d6d178f-34f6-4bff-a01c-0a2f8fe909e4')
def test_update_port_with_cidr_address_pair(self):
# Update allowed address pair with cidr
cidr = str(netaddr.IPNetwork(CONF.network.tenant_network_cidr))
self._update_port_with_address(cidr)
@test.attr(type='smoke')
+ @test.idempotent_id('b3f20091-6cd5-472b-8487-3516137df933')
def test_update_port_with_multiple_ip_mac_address_pair(self):
# Create an ip _address and mac_address through port create
resp = self.client.create_port(network_id=self.network['id'])
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 1257699..5168219 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -16,10 +16,12 @@
import netaddr
import random
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
+from tempest import test
CONF = config.CONF
@@ -93,6 +95,7 @@
port_mac).format()
return real_ip, eui_ip
+ @test.idempotent_id('e5517e62-6f16-430d-a672-f80875493d4c')
def test_dhcpv6_stateless_eui64(self):
"""When subnets configured with RAs SLAAC (AOM=100) and DHCP stateless
(AOM=110) both for radvd and dnsmasq, port shall receive IP address
@@ -111,6 +114,7 @@
'ipv6_ra_mode=%s and ipv6_address_mode=%s') % (
real_ip, eui_ip, ra_mode, add_mode))
+ @test.idempotent_id('ae2f4a5d-03ff-4c42-a3b0-ce2fcb7ea832')
def test_dhcpv6_stateless_no_ra(self):
"""When subnets configured with dnsmasq SLAAC and DHCP stateless
and there is no radvd, port shall receive IP address calculated
@@ -132,6 +136,7 @@
ra_mode if ra_mode else "Off",
add_mode if add_mode else "Off"))
+ @test.idempotent_id('81f18ef6-95b5-4584-9966-10d480b7496a')
def test_dhcpv6_invalid_options(self):
"""Different configurations for radvd and dnsmasq are not allowed"""
for ra_mode, add_mode in (
@@ -144,11 +149,12 @@
):
kwargs = {'ipv6_ra_mode': ra_mode,
'ipv6_address_mode': add_mode}
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_subnet,
self.network,
**kwargs)
+ @test.idempotent_id('21635b6f-165a-4d42-bf49-7d195e47342f')
def test_dhcpv6_stateless_no_ra_no_dhcp(self):
"""If no radvd option and no dnsmasq option is configured
port shall receive IP from fixed IPs list of subnet.
@@ -161,6 +167,7 @@
'but shall be taken from fixed IPs') % (
real_ip, eui_ip))
+ @test.idempotent_id('4544adf7-bb5f-4bdc-b769-b3e77026cef2')
def test_dhcpv6_two_subnets(self):
"""When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
and other IPv6 is with DHCP stateful, port shall receive EUI-64 IP
@@ -214,6 +221,7 @@
real_dhcp_ip,
str(dhcp_ip)))
+ @test.idempotent_id('4256c61d-c538-41ea-9147-3c450c36669e')
def test_dhcpv6_64_subnets(self):
"""When one IPv6 subnet configured with dnsmasq SLAAC or DHCP stateless
and other IPv4 is with DHCP of IPv4, port shall receive EUI-64 IP
@@ -263,6 +271,7 @@
real_dhcp_ip,
str(dhcp_ip)))
+ @test.idempotent_id('4ab211a0-276f-4552-9070-51e27f58fecf')
def test_dhcp_stateful(self):
"""With all options below, DHCPv6 shall allocate first
address from subnet pool to port.
@@ -288,6 +297,7 @@
port_ip,
str(dhcp_ip)))
+ @test.idempotent_id('51a5e97f-f02e-4e4e-9a17-a69811d300e3')
def test_dhcp_stateful_fixedips(self):
"""With all options below, port shall be able to get
requested IP from fixed IP range not depending on
@@ -316,6 +326,7 @@
"port create request: %s") % (
port_ip, ip))
+ @test.idempotent_id('98244d88-d990-4570-91d4-6b25d70d08af')
def test_dhcp_stateful_fixedips_outrange(self):
"""When port gets IP address from fixed IP range it
shall be checked if it's from subnets range.
@@ -327,12 +338,13 @@
subnet["allocation_pools"][0]["end"])
ip = netaddr.IPAddress(random.randrange(
ip_range.last + 1, ip_range.last + 10)).format()
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.create_port,
self.network,
fixed_ips=[{'subnet_id': subnet['id'],
'ip_address': ip}])
+ @test.idempotent_id('57b8302b-cba9-4fbb-8835-9168df029051')
def test_dhcp_stateful_fixedips_duplicate(self):
"""When port gets IP address from fixed IP range it
shall be checked if it's not duplicate.
@@ -348,7 +360,7 @@
fixed_ips=[
{'subnet_id': subnet['id'],
'ip_address': ip}])
- self.assertRaisesRegexp(exceptions.Conflict,
+ self.assertRaisesRegexp(lib_exc.Conflict,
"object with that identifier already exists",
self.create_port,
self.network,
@@ -365,6 +377,7 @@
body = self.client.show_port(port['port_id'])
return subnet, body['port']
+ @test.idempotent_id('e98f65db-68f4-4330-9fea-abd8c5192d4d')
def test_dhcp_stateful_router(self):
"""With all options below the router interface shall
receive DHCPv6 IP address from allocation pool.
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index 54c3cb9..bce8efe 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -19,7 +19,6 @@
class ExtensionsTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -37,6 +36,7 @@
super(ExtensionsTestJSON, cls).resource_setup()
@test.attr(type='smoke')
+ @test.idempotent_id('ef28c7e6-e646-4979-9d67-deb207bc5564')
def test_list_show_extensions(self):
# List available extensions for the tenant
expected_alias = ['security-group', 'l3_agent_scheduler',
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index bd70323..612c20a 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -19,7 +19,6 @@
class ExtraDHCPOptionsTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations with the Extra DHCP Options Neutron API
@@ -55,6 +54,7 @@
]
@test.attr(type='smoke')
+ @test.idempotent_id('d2c17063-3767-4a24-be4f-a23dbfa133c9')
def test_create_list_port_with_extra_dhcp_options(self):
# Create a port with Extra DHCP Options
body = self.client.create_port(
@@ -71,6 +71,7 @@
self._confirm_extra_dhcp_options(port[0], self.extra_dhcp_opts)
@test.attr(type='smoke')
+ @test.idempotent_id('9a6aebf4-86ee-4f47-b07a-7f7232c55607')
def test_update_show_port_with_extra_dhcp_options(self):
# Update port with extra dhcp options
name = data_utils.rand_name('new-port-name')
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 1151c5d..cc88852 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -24,7 +24,6 @@
class FloatingIPTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Quantum API using the REST client for
@@ -65,6 +64,7 @@
cls.create_port(cls.network)
@test.attr(type='smoke')
+ @test.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e8718')
def test_create_list_show_update_delete_floating_ip(self):
# Creates a floating IP
body = self.client.create_floatingip(
@@ -119,6 +119,7 @@
self.assertIsNone(updated_floating_ip['router_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('e1f6bffd-442f-4668-b30e-df13f2705e77')
def test_floating_ip_delete_port(self):
# Create a floating IP
body = self.client.create_floatingip(
@@ -144,6 +145,7 @@
self.assertIsNone(shown_floating_ip['router_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('1bb2f731-fe5a-4b8c-8409-799ade1bed4d')
def test_floating_ip_update_different_router(self):
# Associate a floating IP to a port on a router
body = self.client.create_floatingip(
@@ -170,6 +172,7 @@
self.assertIsNotNone(updated_floating_ip['fixed_ip_address'])
@test.attr(type='smoke')
+ @test.idempotent_id('36de4bd0-f09c-43e3-a8e1-1decc1ffd3a5')
def test_create_floating_ip_specifying_a_fixed_ip_address(self):
body = self.client.create_floatingip(
floating_network_id=self.ext_net_id,
@@ -187,6 +190,7 @@
self.assertIsNone(floating_ip['floatingip']['port_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('45c4c683-ea97-41ef-9c51-5e9802f2f3d7')
def test_create_update_floatingip_with_port_multiple_ip_address(self):
# Find out ips that can be used for tests
ips = list(netaddr.IPNetwork(self.subnet['cidr']))
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index 82f0519..c4c547c 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -14,17 +14,18 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class FloatingIPNegativeTestJSON(base.BaseNetworkTest):
- _interface = 'json'
+
"""
Test the following negative operations for floating ips:
@@ -48,16 +49,18 @@
cls.port = cls.create_port(cls.network)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('22996ea8-4a81-4b27-b6e1-fa5df92fa5e8')
def test_create_floatingip_with_port_ext_net_unreachable(self):
- self.assertRaises(exceptions.NotFound, self.client.create_floatingip,
+ self.assertRaises(lib_exc.NotFound, self.client.create_floatingip,
floating_network_id=self.ext_net_id,
port_id=self.port['id'],
fixed_ip_address=self.port['fixed_ips'][0]
['ip_address'])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('50b9aeb4-9f0b-48ee-aa31-fa955a48ff54')
def test_create_floatingip_in_private_network(self):
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.create_floatingip,
floating_network_id=self.network['id'],
port_id=self.port['id'],
@@ -65,6 +68,7 @@
['ip_address'])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('6b3b8797-6d43-4191-985c-c48b773eb429')
def test_associate_floatingip_port_ext_net_unreachable(self):
# Create floating ip
body = self.client.create_floatingip(
@@ -72,7 +76,7 @@
floating_ip = body['floatingip']
self.addCleanup(self.client.delete_floatingip, floating_ip['id'])
# Associate floating IP to the other port
- self.assertRaises(exceptions.NotFound, self.client.update_floatingip,
+ self.assertRaises(lib_exc.NotFound, self.client.update_floatingip,
floating_ip['id'], port_id=self.port['id'],
fixed_ip_address=self.port['fixed_ips'][0]
['ip_address'])
diff --git a/tempest/api/network/test_fwaas_extensions.py b/tempest/api/network/test_fwaas_extensions.py
index 8104567..d97a60c 100644
--- a/tempest/api/network/test_fwaas_extensions.py
+++ b/tempest/api/network/test_fwaas_extensions.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import config
@@ -22,7 +24,6 @@
class FWaaSExtensionTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -63,7 +64,7 @@
try:
self.client.delete_firewall_policy(policy_id)
# if policy is not found, this means it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
def _try_delete_rule(self, rule_id):
@@ -71,7 +72,7 @@
try:
self.client.delete_firewall_rule(rule_id)
# if rule is not found, this means it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
def _try_delete_firewall(self, fw_id):
@@ -79,7 +80,7 @@
try:
self.client.delete_firewall(fw_id)
# if firewall is not found, this means it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
self.client.wait_for_resource_deletion('firewall', fw_id)
@@ -98,6 +99,7 @@
(fw_id, target_states))
raise exceptions.TimeoutException(m)
+ @test.idempotent_id('1b84cf01-9c09-4ce7-bc72-b15e39076468')
def test_list_firewall_rules(self):
# List firewall rules
fw_rules = self.client.list_firewall_rules()
@@ -115,6 +117,7 @@
m['ip_version'],
m['enabled']) for m in fw_rules])
+ @test.idempotent_id('563564f7-7077-4f5e-8cdc-51f37ae5a2b9')
def test_create_update_delete_firewall_rule(self):
# Create firewall rule
body = self.client.create_firewall_rule(
@@ -135,12 +138,14 @@
self.assertNotIn(fw_rule_id,
[m['id'] for m in fw_rules['firewall_rules']])
+ @test.idempotent_id('3ff8c08e-26ff-4034-ae48-810ed213a998')
def test_show_firewall_rule(self):
# show a created firewall rule
fw_rule = self.client.show_firewall_rule(self.fw_rule['id'])
for key, value in fw_rule['firewall_rule'].iteritems():
self.assertEqual(self.fw_rule[key], value)
+ @test.idempotent_id('1086dd93-a4c0-4bbb-a1bd-6d4bc62c199f')
def test_list_firewall_policies(self):
fw_policies = self.client.list_firewall_policies()
fw_policies = fw_policies['firewall_policies']
@@ -151,6 +156,7 @@
m['name'],
m['firewall_rules']) for m in fw_policies])
+ @test.idempotent_id('bbf37b6c-498c-421e-9c95-45897d3ed775')
def test_create_update_delete_firewall_policy(self):
# Create firewall policy
body = self.client.create_firewall_policy(
@@ -173,6 +179,7 @@
fw_policies = fw_policies['firewall_policies']
self.assertNotIn(fw_policy_id, [m['id'] for m in fw_policies])
+ @test.idempotent_id('1df59b3a-517e-41d4-96f6-fc31cf4ecff2')
def test_show_firewall_policy(self):
# show a created firewall policy
fw_policy = self.client.show_firewall_policy(self.fw_policy['id'])
@@ -180,6 +187,7 @@
for key, value in fw_policy.iteritems():
self.assertEqual(self.fw_policy[key], value)
+ @test.idempotent_id('02082a03-3cdd-4789-986a-1327dd80bfb7')
def test_create_show_delete_firewall(self):
# Create tenant network resources required for an ACTIVE firewall
network = self.create_network()
@@ -224,6 +232,7 @@
self.client.delete_firewall(firewall_id)
@test.attr(type='smoke')
+ @test.idempotent_id('53305b4b-9897-4e01-87c0-2ae386083180')
def test_firewall_rule_insertion_position_removal_rule_from_policy(self):
# Create firewall rule
body = self.client.create_firewall_rule(
@@ -290,6 +299,7 @@
return [ruleid for ruleid in fw_policy['firewall_policy']
['firewall_rules']]
+ @test.idempotent_id('8515ca8a-0d2f-4298-b5ff-6f924e4587ca')
def test_update_firewall_policy_audited_attribute(self):
# Create firewall rule
body = self.client.create_firewall_rule(
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index df76757..6872dfa 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -21,7 +21,6 @@
class LoadBalancerTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -82,6 +81,7 @@
self.assertIn(value, objs)
@test.attr(type='smoke')
+ @test.idempotent_id('c96dbfab-4a80-4e74-a535-e950b5bedd47')
def test_list_vips(self):
# Verify the vIP exists in the list of all vIPs
body = self.client.list_vips()
@@ -89,6 +89,7 @@
self.assertIn(self.vip['id'], [v['id'] for v in vips])
@test.attr(type='smoke')
+ @test.idempotent_id('b8853f65-5089-4e69-befd-041a143427ff')
def test_list_vips_with_filter(self):
name = data_utils.rand_name('vip-')
body = self.client.create_pool(name=data_utils.rand_name("pool-"),
@@ -106,6 +107,7 @@
admin_state_up=False)
@test.attr(type='smoke')
+ @test.idempotent_id('27f56083-9af9-4a48-abe9-ca1bcc6c9035')
def test_create_update_delete_pool_vip(self):
# Creates a vip
name = data_utils.rand_name('vip-')
@@ -162,6 +164,7 @@
self.client.delete_pool(pool['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('0435a95e-1d19-4d90-9e9f-3b979e9ad089')
def test_show_vip(self):
# Verifies the details of a vip
body = self.client.show_vip(self.vip['id'])
@@ -172,6 +175,7 @@
self.assertEqual(self.vip[key], value)
@test.attr(type='smoke')
+ @test.idempotent_id('6e7a7d31-8451-456d-b24a-e50479ce42a7')
def test_show_pool(self):
# Here we need to new pool without any dependence with vips
body = self.client.create_pool(name=data_utils.rand_name("pool-"),
@@ -189,6 +193,7 @@
self.assertEqual(value, shown_pool[key])
@test.attr(type='smoke')
+ @test.idempotent_id('d1ab1ffa-e06a-487f-911f-56418cb27727')
def test_list_pools(self):
# Verify the pool exists in the list of all pools
body = self.client.list_pools()
@@ -196,6 +201,7 @@
self.assertIn(self.pool['id'], [p['id'] for p in pools])
@test.attr(type='smoke')
+ @test.idempotent_id('27cc4c1a-caac-4273-b983-2acb4afaad4f')
def test_list_pools_with_filters(self):
attr_exceptions = ['status', 'vip_id', 'members', 'provider',
'status_description']
@@ -207,6 +213,7 @@
admin_state_up=False)
@test.attr(type='smoke')
+ @test.idempotent_id('282d0dfd-5c3a-4c9b-b39c-c99782f39193')
def test_list_members(self):
# Verify the member exists in the list of all members
body = self.client.list_members()
@@ -214,6 +221,7 @@
self.assertIn(self.member['id'], [m['id'] for m in members])
@test.attr(type='smoke')
+ @test.idempotent_id('243b5126-24c6-4879-953e-7c7e32d8a57f')
def test_list_members_with_filters(self):
attr_exceptions = ['status', 'status_description']
self._check_list_with_filter('member', attr_exceptions,
@@ -222,6 +230,7 @@
pool_id=self.pool['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('fb833ee8-9e69-489f-b540-a409762b78b2')
def test_create_update_delete_member(self):
# Creates a member
body = self.client.create_member(address=self.member_address,
@@ -237,6 +246,7 @@
self.client.delete_member(member['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('893cd71f-a7dd-4485-b162-f6ab9a534914')
def test_show_member(self):
# Verifies the details of a member
body = self.client.show_member(self.member['id'])
@@ -247,6 +257,7 @@
self.assertEqual(self.member[key], value)
@test.attr(type='smoke')
+ @test.idempotent_id('8e5822c5-68a4-4224-8d6c-a617741ebc2d')
def test_list_health_monitors(self):
# Verify the health monitor exists in the list of all health monitors
body = self.client.list_health_monitors()
@@ -255,6 +266,7 @@
[h['id'] for h in health_monitors])
@test.attr(type='smoke')
+ @test.idempotent_id('49bac58a-511c-4875-b794-366698211d25')
def test_list_health_monitors_with_filters(self):
attr_exceptions = ['status', 'status_description', 'pools']
self._check_list_with_filter('health_monitor', attr_exceptions,
@@ -262,6 +274,7 @@
timeout=2)
@test.attr(type='smoke')
+ @test.idempotent_id('e8ce05c4-d554-4d1e-a257-ad32ce134bb5')
def test_create_update_delete_health_monitor(self):
# Creates a health_monitor
body = self.client.create_health_monitor(delay=4,
@@ -279,6 +292,7 @@
body = self.client.delete_health_monitor(health_monitor['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('d3e1aebc-06c2-49b3-9816-942af54012eb')
def test_create_health_monitor_http_type(self):
hm_type = "HTTP"
body = self.client.create_health_monitor(delay=4,
@@ -291,6 +305,7 @@
self.assertEqual(hm_type, health_monitor['type'])
@test.attr(type='smoke')
+ @test.idempotent_id('0eff9f67-90fb-4bb1-b4ed-c5fda99fff0c')
def test_update_health_monitor_http_method(self):
body = self.client.create_health_monitor(delay=4,
max_retries=3,
@@ -310,6 +325,7 @@
self.assertEqual("290", updated_health_monitor['expected_codes'])
@test.attr(type='smoke')
+ @test.idempotent_id('08e126ab-1407-483f-a22e-b11cc032ca7c')
def test_show_health_monitor(self):
# Verifies the details of a health_monitor
body = self.client.show_health_monitor(self.health_monitor['id'])
@@ -320,6 +336,7 @@
self.assertEqual(self.health_monitor[key], value)
@test.attr(type='smoke')
+ @test.idempotent_id('87f7628e-8918-493d-af50-0602845dbb5b')
def test_associate_disassociate_health_monitor_with_pool(self):
# Verify that a health monitor can be associated with a pool
self.client.associate_health_monitor_with_pool(
@@ -345,6 +362,7 @@
[p['pool_id'] for p in health_monitor['pools']])
@test.attr(type='smoke')
+ @test.idempotent_id('525fc7dc-be24-408d-938d-822e9783e027')
def test_get_lb_pool_stats(self):
# Verify the details of pool stats
body = self.client.list_lb_pool_stats(self.pool['id'])
@@ -355,6 +373,7 @@
self.assertIn("bytes_out", stats)
@test.attr(type='smoke')
+ @test.idempotent_id('66236be2-5121-4047-8cde-db4b83b110a5')
def test_update_list_of_health_monitors_associated_with_pool(self):
(self.client.associate_health_monitor_with_pool
(self.health_monitor['id'], self.pool['id']))
@@ -369,6 +388,7 @@
(self.health_monitor['id'], self.pool['id']))
@test.attr(type='smoke')
+ @test.idempotent_id('44ec9b40-b501-41e2-951f-4fc673b15ac0')
def test_update_admin_state_up_of_pool(self):
self.client.update_pool(self.pool['id'],
admin_state_up=False)
@@ -377,6 +397,7 @@
self.assertFalse(pool['admin_state_up'])
@test.attr(type='smoke')
+ @test.idempotent_id('466a9d4c-37c6-4ea2-b807-133437beb48c')
def test_show_vip_associated_with_pool(self):
body = self.client.show_pool(self.pool['id'])
pool = body['pool']
@@ -386,6 +407,7 @@
self.assertEqual(self.vip['id'], vip['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('7b97694e-69d0-4151-b265-e1052a465aa8')
def test_show_members_associated_with_pool(self):
body = self.client.show_pool(self.pool['id'])
members = body['pool']['members']
@@ -396,6 +418,7 @@
self.assertIsNotNone(body['member']['admin_state_up'])
@test.attr(type='smoke')
+ @test.idempotent_id('73ed6f27-595b-4b2c-969c-dbdda6b8ab34')
def test_update_pool_related_to_member(self):
# Create new pool
body = self.client.create_pool(name=data_utils.rand_name("pool-"),
@@ -416,6 +439,7 @@
pool_id=self.pool['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('cf63f071-bbe3-40ba-97a0-a33e11923162')
def test_update_member_weight(self):
self.client.update_member(self.member['id'],
weight=2)
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 6ba1ea4..8e4ee87 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -1,7 +1,5 @@
# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
#
-# Author: Emilien Macchi <emilien.macchi@enovance.com>
-#
# 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
@@ -24,7 +22,6 @@
class MeteringTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -67,6 +64,7 @@
self.assertEqual(len(rules['metering_label_rules']), 0)
@test.attr(type='smoke')
+ @test.idempotent_id('e2fb2f8c-45bf-429a-9f17-171c70444612')
def test_list_metering_labels(self):
# Verify label filtering
body = self.admin_client.list_metering_labels(id=33)
@@ -74,6 +72,7 @@
self.assertEqual(0, len(metering_labels))
@test.attr(type='smoke')
+ @test.idempotent_id('ec8e15ff-95d0-433b-b8a6-b466bddb1e50')
def test_create_delete_metering_label_with_filters(self):
# Creates a label
name = data_utils.rand_name('metering-label-')
@@ -90,6 +89,7 @@
self.assertEqual(len(labels['metering_labels']), 1)
@test.attr(type='smoke')
+ @test.idempotent_id('30abb445-0eea-472e-bd02-8649f54a5968')
def test_show_metering_label(self):
# Verifies the details of a label
body = self.admin_client.show_metering_label(self.metering_label['id'])
@@ -102,6 +102,7 @@
metering_label['description'])
@test.attr(type='smoke')
+ @test.idempotent_id('cc832399-6681-493b-9d79-0202831a1281')
def test_list_metering_label_rules(self):
# Verify rule filtering
body = self.admin_client.list_metering_label_rules(id=33)
@@ -109,6 +110,7 @@
self.assertEqual(0, len(metering_label_rules))
@test.attr(type='smoke')
+ @test.idempotent_id('f4d547cd-3aee-408f-bf36-454f8825e045')
def test_create_delete_metering_label_rule_with_filters(self):
# Creates a rule
remote_ip_prefix = ("10.0.1.0/24" if self._ip_version == 4
@@ -127,6 +129,7 @@
self.assertEqual(len(rules['metering_label_rules']), 1)
@test.attr(type='smoke')
+ @test.idempotent_id('b7354489-96ea-41f3-9452-bace120fb4a7')
def test_show_metering_label_rule(self):
# Verifies the details of a rule
body = (self.admin_client.show_metering_label_rule(
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 65aeb24..0801045 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -15,19 +15,18 @@
import itertools
import netaddr
+from tempest_lib import exceptions as lib_exc
from tempest.api.network import base
from tempest.common import custom_matchers
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class NetworksTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -178,6 +177,7 @@
self.subnets.pop()
@test.attr(type='smoke')
+ @test.idempotent_id('0e269138-0da6-4efc-a46d-578161e7b221')
def test_create_update_delete_network_subnet(self):
# Create a network
name = data_utils.rand_name('network-')
@@ -200,6 +200,7 @@
self.assertEqual(updated_subnet['name'], new_name)
@test.attr(type='smoke')
+ @test.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
def test_show_network(self):
# Verify the details of a network
body = self.client.show_network(self.network['id'])
@@ -208,6 +209,7 @@
self.assertEqual(network[key], self.network[key])
@test.attr(type='smoke')
+ @test.idempotent_id('867819bb-c4b6-45f7-acf9-90edcf70aa5e')
def test_show_network_fields(self):
# Verify specific fields of a network
fields = ['id', 'name']
@@ -219,6 +221,7 @@
self.assertEqual(network[field_name], self.network[field_name])
@test.attr(type='smoke')
+ @test.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
def test_list_networks(self):
# Verify the network exists in the list of all networks
body = self.client.list_networks()
@@ -227,6 +230,7 @@
self.assertNotEmpty(networks, "Created network not found in the list")
@test.attr(type='smoke')
+ @test.idempotent_id('6ae6d24f-9194-4869-9c85-c313cb20e080')
def test_list_networks_fields(self):
# Verify specific fields of the networks
fields = ['id', 'name']
@@ -237,6 +241,7 @@
self.assertEqual(sorted(network.keys()), sorted(fields))
@test.attr(type='smoke')
+ @test.idempotent_id('bd635d81-6030-4dd1-b3b9-31ba0cfdf6cc')
def test_show_subnet(self):
# Verify the details of a subnet
body = self.client.show_subnet(self.subnet['id'])
@@ -247,6 +252,7 @@
self.assertEqual(subnet[key], self.subnet[key])
@test.attr(type='smoke')
+ @test.idempotent_id('270fff0b-8bfc-411f-a184-1e8fd35286f0')
def test_show_subnet_fields(self):
# Verify specific fields of a subnet
fields = ['id', 'network_id']
@@ -258,6 +264,7 @@
self.assertEqual(subnet[field_name], self.subnet[field_name])
@test.attr(type='smoke')
+ @test.idempotent_id('db68ba48-f4ea-49e9-81d1-e367f6d0b20a')
def test_list_subnets(self):
# Verify the subnet exists in the list of all subnets
body = self.client.list_subnets()
@@ -266,6 +273,7 @@
self.assertNotEmpty(subnets, "Created subnet not found in the list")
@test.attr(type='smoke')
+ @test.idempotent_id('842589e3-9663-46b0-85e4-7f01273b0412')
def test_list_subnets_fields(self):
# Verify specific fields of subnets
fields = ['id', 'network_id']
@@ -280,10 +288,11 @@
try:
self.client.delete_network(net_id)
# if network is not found, this means it was deleted in the test
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@test.attr(type='smoke')
+ @test.idempotent_id('f04f61a9-b7f3-4194-90b2-9bcf660d1bfe')
def test_delete_network_with_subnet(self):
# Creates a network
name = data_utils.rand_name('network-')
@@ -300,7 +309,7 @@
body = self.client.delete_network(net_id)
# Verify that the subnet got automatically deleted.
- self.assertRaises(exceptions.NotFound, self.client.show_subnet,
+ self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
subnet_id)
# Since create_subnet adds the subnet to the delete list, and it is
@@ -309,34 +318,41 @@
self.subnets.pop()
@test.attr(type='smoke')
+ @test.idempotent_id('d2d596e2-8e76-47a9-ac51-d4648009f4d3')
def test_create_delete_subnet_without_gateway(self):
self._create_verify_delete_subnet()
@test.attr(type='smoke')
+ @test.idempotent_id('9393b468-186d-496d-aa36-732348cd76e7')
def test_create_delete_subnet_with_gw(self):
self._create_verify_delete_subnet(
**self.subnet_dict(['gateway']))
@test.attr(type='smoke')
+ @test.idempotent_id('bec949c4-3147-4ba6-af5f-cd2306118404')
def test_create_delete_subnet_with_allocation_pools(self):
self._create_verify_delete_subnet(
**self.subnet_dict(['allocation_pools']))
@test.attr(type='smoke')
+ @test.idempotent_id('8217a149-0c6c-4cfb-93db-0486f707d13f')
def test_create_delete_subnet_with_gw_and_allocation_pools(self):
self._create_verify_delete_subnet(**self.subnet_dict(
['gateway', 'allocation_pools']))
@test.attr(type='smoke')
+ @test.idempotent_id('d830de0a-be47-468f-8f02-1fd996118289')
def test_create_delete_subnet_with_host_routes_and_dns_nameservers(self):
self._create_verify_delete_subnet(
**self.subnet_dict(['host_routes', 'dns_nameservers']))
@test.attr(type='smoke')
+ @test.idempotent_id('94ce038d-ff0a-4a4c-a56b-09da3ca0b55d')
def test_create_delete_subnet_with_dhcp_enabled(self):
self._create_verify_delete_subnet(enable_dhcp=True)
@test.attr(type='smoke')
+ @test.idempotent_id('3d3852eb-3009-49ec-97ac-5ce83b73010a')
def test_update_subnet_gw_dns_host_routes_dhcp(self):
network = self.create_network()
self.addCleanup(self._delete_network, network)
@@ -370,12 +386,14 @@
self._compare_resource_attrs(updated_subnet, kwargs)
@test.attr(type='smoke')
+ @test.idempotent_id('a4d9ec4c-0306-4111-a75c-db01a709030b')
def test_create_delete_subnet_all_attributes(self):
self._create_verify_delete_subnet(
enable_dhcp=True,
**self.subnet_dict(['gateway', 'host_routes', 'dns_nameservers']))
@test.attr(type='smoke')
+ @test.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
def test_external_network_visibility(self):
"""Verifies user can see external networks but not subnets."""
body = self.client.list_networks(**{'router:external': True})
@@ -399,7 +417,6 @@
class BulkNetworkOpsTestJSON(base.BaseNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -448,6 +465,7 @@
self.assertNotIn(n['id'], ports_list)
@test.attr(type='smoke')
+ @test.idempotent_id('d4f9024d-1e28-4fc1-a6b1-25dbc6fa11e2')
def test_bulk_create_delete_network(self):
# Creates 2 networks in one request
network_names = [data_utils.rand_name('network-'),
@@ -463,23 +481,27 @@
self.assertIn(n['id'], networks_list)
@test.attr(type='smoke')
+ @test.idempotent_id('8936533b-c0aa-4f29-8e53-6cc873aec489')
def test_bulk_create_delete_subnet(self):
networks = [self.create_network(), self.create_network()]
# Creates 2 subnets in one request
- cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
- mask_bits = CONF.network.tenant_network_mask_bits
+ if self._ip_version == 4:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+ mask_bits = CONF.network.tenant_network_mask_bits
+ else:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
+ mask_bits = CONF.network.tenant_network_v6_mask_bits
+
cidrs = [subnet_cidr for subnet_cidr in cidr.subnet(mask_bits)]
+
names = [data_utils.rand_name('subnet-') for i in range(len(networks))]
subnets_list = []
- # TODO(raies): "for IPv6, version list [4, 6] will be used.
- # and cidr for IPv6 will be of IPv6"
- ip_version = [4, 4]
for i in range(len(names)):
p1 = {
'network_id': networks[i]['id'],
'cidr': str(cidrs[(i)]),
'name': names[i],
- 'ip_version': ip_version[i]
+ 'ip_version': self._ip_version
}
subnets_list.append(p1)
del subnets_list[1]['name']
@@ -494,6 +516,7 @@
self.assertIn(n['id'], subnets_list)
@test.attr(type='smoke')
+ @test.idempotent_id('48037ff2-e889-4c3b-b86a-8e3f34d2d060')
def test_bulk_create_delete_port(self):
networks = [self.create_network(), self.create_network()]
# Creates 2 ports in one request
@@ -519,10 +542,15 @@
self.assertIn(n['id'], ports_list)
+class BulkNetworkOpsIpV6TestJSON(BulkNetworkOpsTestJSON):
+ _ip_version = 6
+
+
class NetworksIpV6TestJSON(NetworksTestJSON):
_ip_version = 6
@test.attr(type='smoke')
+ @test.idempotent_id('e41a4888-65a6-418c-a095-f7c2ef4ad59a')
def test_create_delete_subnet_with_gw(self):
net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
gateway = str(netaddr.IPAddress(net.first + 2))
@@ -533,6 +561,7 @@
self.assertEqual(subnet['gateway_ip'], gateway)
@test.attr(type='smoke')
+ @test.idempotent_id('ebb4fd95-524f-46af-83c1-0305b239338f')
def test_create_delete_subnet_with_default_gw(self):
net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
gateway_ip = str(netaddr.IPAddress(net.first + 1))
@@ -543,6 +572,7 @@
self.assertEqual(subnet['gateway_ip'], gateway_ip)
@test.attr(type='smoke')
+ @test.idempotent_id('a9653883-b2a4-469b-8c3c-4518430a7e55')
def test_create_list_subnet_with_no_gw64_one_network(self):
name = data_utils.rand_name('network-')
network = self.create_network(name)
@@ -581,6 +611,7 @@
super(NetworksIpV6TestAttrs, cls).resource_setup()
@test.attr(type='smoke')
+ @test.idempotent_id('da40cd1b-a833-4354-9a85-cd9b8a3b74ca')
def test_create_delete_subnet_with_v6_attributes_stateful(self):
self._create_verify_delete_subnet(
gateway=self._subnet_data[self._ip_version]['gateway'],
@@ -588,12 +619,14 @@
ipv6_address_mode='dhcpv6-stateful')
@test.attr(type='smoke')
+ @test.idempotent_id('176b030f-a923-4040-a755-9dc94329e60c')
def test_create_delete_subnet_with_v6_attributes_slaac(self):
self._create_verify_delete_subnet(
ipv6_ra_mode='slaac',
ipv6_address_mode='slaac')
@test.attr(type='smoke')
+ @test.idempotent_id('7d410310-8c86-4902-adf9-865d08e31adb')
def test_create_delete_subnet_with_v6_attributes_stateless(self):
self._create_verify_delete_subnet(
ipv6_ra_mode='dhcpv6-stateless',
@@ -614,12 +647,13 @@
self.assertNotIn(subnet_slaac['id'], subnet_ids,
"Subnet wasn't deleted")
self.assertRaisesRegexp(
- exceptions.Conflict,
+ lib_exc.Conflict,
"There are one or more ports still in use on the network",
self.client.delete_network,
slaac_network['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('88554555-ebf8-41ef-9300-4926d45e06e9')
def test_create_delete_slaac_subnet_with_ports(self):
"""Test deleting subnet with SLAAC ports
@@ -630,6 +664,7 @@
self._test_delete_subnet_with_ports("slaac")
@test.attr(type='smoke')
+ @test.idempotent_id('2de6ab5a-fcf0-4144-9813-f91a940291f1')
def test_create_delete_stateless_subnet_with_ports(self):
"""Test deleting subnet with DHCPv6 stateless ports
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index bc3ab68..1002295 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -14,41 +14,46 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class NetworksNegativeTestJSON(base.BaseNetworkTest):
- _interface = 'json'
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('9293e937-824d-42d2-8d5b-e985ea67002a')
def test_show_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
- self.assertRaises(exceptions.NotFound, self.client.show_network,
+ self.assertRaises(lib_exc.NotFound, self.client.show_network,
non_exist_id)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('d746b40c-5e09-4043-99f7-cba1be8b70df')
def test_show_non_existent_subnet(self):
non_exist_id = data_utils.rand_name('subnet')
- self.assertRaises(exceptions.NotFound, self.client.show_subnet,
+ self.assertRaises(lib_exc.NotFound, self.client.show_subnet,
non_exist_id)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('a954861d-cbfd-44e8-b0a9-7fab111f235d')
def test_show_non_existent_port(self):
non_exist_id = data_utils.rand_name('port')
- self.assertRaises(exceptions.NotFound, self.client.show_port,
+ self.assertRaises(lib_exc.NotFound, self.client.show_port,
non_exist_id)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('98bfe4e3-574e-4012-8b17-b2647063de87')
def test_update_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
- self.assertRaises(exceptions.NotFound, self.client.update_network,
+ self.assertRaises(lib_exc.NotFound, self.client.update_network,
non_exist_id, name="new_name")
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('03795047-4a94-4120-a0a1-bd376e36fd4e')
def test_delete_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
- self.assertRaises(exceptions.NotFound, self.client.delete_network,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_network,
non_exist_id)
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index bf85e90..33211fc 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -27,7 +27,6 @@
class PortsTestJSON(sec_base.BaseSecGroupTest):
- _interface = 'json'
"""
Test the following operations for ports:
@@ -52,6 +51,7 @@
self.assertFalse(port_id in [n['id'] for n in ports_list])
@test.attr(type='smoke')
+ @test.idempotent_id('c72c1c0c-2193-4aca-aaa4-b1442640f51c')
def test_create_update_delete_port(self):
# Verify port creation
body = self.client.create_port(network_id=self.network['id'])
@@ -68,6 +68,7 @@
self.assertEqual(updated_port['name'], new_name)
self.assertFalse(updated_port['admin_state_up'])
+ @test.idempotent_id('67f1b811-f8db-43e2-86bd-72c074d4a42c')
def test_create_bulk_port(self):
network1 = self.network
name = data_utils.rand_name('network-')
@@ -97,6 +98,7 @@
return netaddr.IPAddress(cidr)
@test.attr(type='smoke')
+ @test.idempotent_id('0435f278-40ae-48cb-a404-b8a087bc09b1')
def test_create_port_in_allowed_allocation_pools(self):
network = self.create_network()
net_id = network['id']
@@ -115,6 +117,7 @@
self.assertIn(ip_address, ip_range)
@test.attr(type='smoke')
+ @test.idempotent_id('c9a685bd-e83f-499c-939f-9f7863ca259f')
def test_show_port(self):
# Verify the details of port
body = self.client.show_port(self.port['id'])
@@ -128,6 +131,7 @@
(port, excluded_keys=['extra_dhcp_opts']))
@test.attr(type='smoke')
+ @test.idempotent_id('45fcdaf2-dab0-4c13-ac6c-fcddfb579dbd')
def test_show_port_fields(self):
# Verify specific fields of a port
fields = ['id', 'mac_address']
@@ -139,6 +143,7 @@
self.assertEqual(port[field_name], self.port[field_name])
@test.attr(type='smoke')
+ @test.idempotent_id('cf95b358-3e92-4a29-a148-52445e1ac50e')
def test_list_ports(self):
# Verify the port exists in the list of all ports
body = self.client.list_ports()
@@ -147,6 +152,7 @@
self.assertNotEmpty(ports, "Created port not found in the list")
@test.attr(type='smoke')
+ @test.idempotent_id('5ad01ed0-0e6e-4c5d-8194-232801b15c72')
def test_port_list_filter_by_router_id(self):
# Create a router
network = self.create_network()
@@ -169,6 +175,7 @@
self.assertEqual(ports[0]['device_id'], router['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('ff7f117f-f034-4e0e-abff-ccef05c454b4')
def test_list_ports_fields(self):
# Verify specific fields of ports
fields = ['id', 'mac_address']
@@ -180,6 +187,7 @@
self.assertEqual(sorted(fields), sorted(port.keys()))
@test.attr(type='smoke')
+ @test.idempotent_id('63aeadd4-3b49-427f-a3b1-19ca81f06270')
def test_create_update_port_with_second_ip(self):
# Create a network with two subnets
network = self.create_network()
@@ -260,17 +268,20 @@
self.assertIn(security_group, port_show['security_groups'])
@test.attr(type='smoke')
+ @test.idempotent_id('58091b66-4ff4-4cc1-a549-05d60c7acd1a')
def test_update_port_with_security_group_and_extra_attributes(self):
self._update_port_with_security_groups(
[data_utils.rand_name('secgroup')])
@test.attr(type='smoke')
+ @test.idempotent_id('edf6766d-3d40-4621-bc6e-2521a44c257d')
def test_update_port_with_two_security_groups_and_extra_attributes(self):
self._update_port_with_security_groups(
[data_utils.rand_name('secgroup'),
data_utils.rand_name('secgroup')])
@test.attr(type='smoke')
+ @test.idempotent_id('13e95171-6cbd-489c-9d7c-3f9c58215c18')
def test_create_show_delete_port_user_defined_mac(self):
# Create a port for a legal mac
body = self.client.create_port(network_id=self.network['id'])
@@ -288,6 +299,7 @@
show_port['mac_address'])
@test.attr(type='smoke')
+ @test.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
def test_create_port_with_no_securitygroups(self):
network = self.create_network()
self.addCleanup(self.client.delete_network, network['id'])
@@ -300,7 +312,6 @@
class PortsAdminExtendedAttrsTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -312,6 +323,7 @@
cls.host_id = socket.gethostname()
@test.attr(type='smoke')
+ @test.idempotent_id('8e8569c1-9ac7-44db-8bc1-f5fb2814f29b')
def test_create_port_binding_ext_attr(self):
post_body = {"network_id": self.network['id'],
"binding:host_id": self.host_id}
@@ -323,6 +335,7 @@
self.assertEqual(self.host_id, host_id)
@test.attr(type='smoke')
+ @test.idempotent_id('6f6c412c-711f-444d-8502-0ac30fbf5dd5')
def test_update_port_binding_ext_attr(self):
post_body = {"network_id": self.network['id']}
body = self.admin_client.create_port(**post_body)
@@ -336,6 +349,7 @@
self.assertEqual(self.host_id, host_id)
@test.attr(type='smoke')
+ @test.idempotent_id('1c82a44a-6c6e-48ff-89e1-abe7eaf8f9f8')
def test_list_ports_binding_ext_attr(self):
# Create a new port
post_body = {"network_id": self.network['id']}
@@ -361,6 +375,7 @@
self.assertEqual(self.host_id, listed_port[0]['binding:host_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('b54ac0ff-35fc-4c79-9ca3-c7dbd4ea4f13')
def test_show_port_binding_ext_attr(self):
body = self.admin_client.create_port(network_id=self.network['id'])
port = body['port']
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 210a8af..1388b3b 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -25,7 +25,6 @@
class RoutersTest(base.BaseRouterTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -52,6 +51,7 @@
return router
@test.attr(type='smoke')
+ @test.idempotent_id('f64403e2-8483-4b34-8ccd-b09a87bcc68c')
def test_create_show_list_update_delete_router(self):
# Create a router
# NOTE(salv-orlando): Do not invoke self.create_router
@@ -90,6 +90,7 @@
self.assertEqual(show_body['router']['name'], updated_name)
@test.attr(type='smoke')
+ @test.idempotent_id('e54dd3a3-4352-4921-b09d-44369ae17397')
def test_create_router_setting_tenant_id(self):
# Test creating router from admin user setting tenant_id.
test_tenant = data_utils.rand_name('test_tenant_')
@@ -106,6 +107,7 @@
create_body['router']['id'])
self.assertEqual(tenant_id, create_body['router']['tenant_id'])
+ @test.idempotent_id('847257cc-6afd-4154-b8fb-af49f5670ce8')
@test.requires_ext(extension='ext-gw-mode', service='network')
@test.attr(type='smoke')
def test_create_router_with_default_snat_value(self):
@@ -117,6 +119,7 @@
router['id'], {'network_id': CONF.network.public_network_id,
'enable_snat': True})
+ @test.idempotent_id('ea74068d-09e9-4fd7-8995-9b6a1ace920f')
@test.requires_ext(extension='ext-gw-mode', service='network')
@test.attr(type='smoke')
def test_create_router_with_snat_explicit(self):
@@ -136,6 +139,7 @@
exp_ext_gw_info=external_gateway_info)
@test.attr(type='smoke')
+ @test.idempotent_id('b42e6e39-2e37-49cc-a6f4-8467e940900a')
def test_add_remove_router_interface_with_subnet_id(self):
network = self.create_network()
subnet = self.create_subnet(network)
@@ -154,6 +158,7 @@
router['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('2b7d2f37-6748-4d78-92e5-1d590234f0d5')
def test_add_remove_router_interface_with_port_id(self):
network = self.create_network()
self.create_subnet(network)
@@ -198,6 +203,7 @@
map(lambda x: x['subnet_id'], fixed_ips))
@test.attr(type='smoke')
+ @test.idempotent_id('6cc285d8-46bf-4f36-9b1a-783e3008ba79')
def test_update_router_set_gateway(self):
router = self._create_router(data_utils.rand_name('router-'))
self.client.update_router(
@@ -210,6 +216,7 @@
{'network_id': CONF.network.public_network_id})
self._verify_gateway_port(router['id'])
+ @test.idempotent_id('b386c111-3b21-466d-880c-5e72b01e1a33')
@test.requires_ext(extension='ext-gw-mode', service='network')
@test.attr(type='smoke')
def test_update_router_set_gateway_with_snat_explicit(self):
@@ -225,6 +232,7 @@
'enable_snat': True})
self._verify_gateway_port(router['id'])
+ @test.idempotent_id('96536bc7-8262-4fb2-9967-5c46940fa279')
@test.requires_ext(extension='ext-gw-mode', service='network')
@test.attr(type='smoke')
def test_update_router_set_gateway_without_snat(self):
@@ -241,6 +249,7 @@
self._verify_gateway_port(router['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('ad81b7ee-4f81-407b-a19c-17e623f763e8')
def test_update_router_unset_gateway(self):
router = self._create_router(
data_utils.rand_name('router-'),
@@ -253,6 +262,7 @@
device_id=router['id'])
self.assertFalse(list_body['ports'])
+ @test.idempotent_id('f2faf994-97f4-410b-a831-9bc977b64374')
@test.requires_ext(extension='ext-gw-mode', service='network')
@test.attr(type='smoke')
def test_update_router_reset_gateway_without_snat(self):
@@ -270,6 +280,7 @@
'enable_snat': False})
self._verify_gateway_port(router['id'])
+ @test.idempotent_id('c86ac3a8-50bd-4b00-a6b8-62af84a0765c')
@test.requires_ext(extension='extraroute', service='network')
@test.attr(type='smoke')
def test_update_extra_route(self):
@@ -305,6 +316,7 @@
self.client.delete_extra_routes(router_id)
@test.attr(type='smoke')
+ @test.idempotent_id('a8902683-c788-4246-95c7-ad9c6d63a4d9')
def test_update_router_admin_state(self):
self.router = self._create_router(data_utils.rand_name('router-'))
self.assertFalse(self.router['admin_state_up'])
@@ -316,6 +328,7 @@
self.assertTrue(show_body['router']['admin_state_up'])
@test.attr(type='smoke')
+ @test.idempotent_id('802c73c9-c937-4cef-824b-2191e24a6aab')
def test_add_multiple_router_interfaces(self):
network01 = self.create_network(
network_name=data_utils.rand_name('router-network01-'))
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index d571e92..9f76dd2 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -14,18 +14,17 @@
# under the License.
import netaddr
+from tempest_lib import exceptions as lib_exc
from tempest.api.network import base_routers as base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class RoutersNegativeTest(base.BaseRouterTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -41,26 +40,29 @@
CONF.network.tenant_network_v6_cidr)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('37a94fc0-a834-45b9-bd23-9a81d2fd1e22')
def test_router_add_gateway_invalid_network_returns_404(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.update_router,
self.router['id'],
external_gateway_info={
'network_id': self.router['id']})
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('11836a18-0b15-4327-a50b-f0d9dc66bddd')
def test_router_add_gateway_net_not_external_returns_400(self):
alt_network = self.create_network(
network_name=data_utils.rand_name('router-negative-'))
sub_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
self.create_subnet(alt_network, cidr=sub_cidr)
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.update_router,
self.router['id'],
external_gateway_info={
'network_id': alt_network['id']})
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('957751a3-3c68-4fa2-93b6-eb52ea10db6e')
def test_add_router_interfaces_on_overlapping_subnets_returns_400(self):
network01 = self.create_network(
network_name=data_utils.rand_name('router-network01-'))
@@ -70,35 +72,39 @@
subnet02 = self.create_subnet(network02)
self._add_router_interface_with_subnet_id(self.router['id'],
subnet01['id'])
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self._add_router_interface_with_subnet_id,
self.router['id'],
subnet02['id'])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('04df80f9-224d-47f5-837a-bf23e33d1c20')
def test_router_remove_interface_in_use_returns_409(self):
self.client.add_router_interface_with_subnet_id(
self.router['id'], self.subnet['id'])
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.delete_router,
self.router['id'])
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('c2a70d72-8826-43a7-8208-0209e6360c47')
def test_show_non_existent_router_returns_404(self):
router = data_utils.rand_name('non_exist_router')
- self.assertRaises(exceptions.NotFound, self.client.show_router,
+ self.assertRaises(lib_exc.NotFound, self.client.show_router,
router)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('b23d1569-8b0c-4169-8d4b-6abd34fad5c7')
def test_update_non_existent_router_returns_404(self):
router = data_utils.rand_name('non_exist_router')
- self.assertRaises(exceptions.NotFound, self.client.update_router,
+ self.assertRaises(lib_exc.NotFound, self.client.update_router,
router, name="new_name")
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('c7edc5ad-d09d-41e6-a344-5c0c31e2e3e4')
def test_delete_non_existent_router_returns_404(self):
router = data_utils.rand_name('non_exist_router')
- self.assertRaises(exceptions.NotFound, self.client.delete_router,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_router,
router)
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 415dedd..8479013 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -24,7 +24,7 @@
class SecGroupTest(base.BaseSecGroupTest):
- _interface = 'json'
+
_tenant_network_cidr = CONF.network.tenant_network_cidr
@classmethod
@@ -69,6 +69,7 @@
(key, value))
@test.attr(type='smoke')
+ @test.idempotent_id('e30abd17-fef9-4739-8617-dc26da88e686')
def test_list_security_groups(self):
# Verify the that security group belonging to tenant exist in list
body = self.client.list_security_groups()
@@ -81,6 +82,7 @@
self.assertIsNotNone(found, msg)
@test.attr(type='smoke')
+ @test.idempotent_id('bfd128e5-3c92-44b6-9d66-7fe29d22c802')
def test_create_list_update_show_delete_security_group(self):
group_create_body, name = self._create_security_group()
@@ -109,6 +111,7 @@
new_description)
@test.attr(type='smoke')
+ @test.idempotent_id('cfb99e0e-7410-4a3d-8a0c-959a63ee77e9')
def test_create_show_delete_security_group_rule(self):
group_create_body, _ = self._create_security_group()
@@ -140,6 +143,7 @@
rule_list)
@test.attr(type='smoke')
+ @test.idempotent_id('87dfbcf9-1849-43ea-b1e4-efa3eeae9f71')
def test_create_security_group_rule_with_additional_args(self):
"""Verify security group rule with additional arguments works.
@@ -158,11 +162,12 @@
port_range_max)
@test.attr(type='smoke')
+ @test.idempotent_id('c9463db8-b44d-4f52-b6c0-8dbda99f26ce')
def test_create_security_group_rule_with_icmp_type_code(self):
"""Verify security group rule for icmp protocol works.
Specify icmp type (port_range_min) and icmp code
- (port_range_max) with different values. A seperate testcase
+ (port_range_max) with different values. A separate testcase
is added for icmp protocol as icmp validation would be
different from tcp/udp.
"""
@@ -178,6 +183,7 @@
icmp_type, icmp_code)
@test.attr(type='smoke')
+ @test.idempotent_id('c2ed2deb-7a0c-44d8-8b4c-a5825b5c310b')
def test_create_security_group_rule_with_remote_group_id(self):
# Verify creating security group rule with remote_group_id works
sg1_body, _ = self._create_security_group()
@@ -196,6 +202,7 @@
remote_group_id=remote_id)
@test.attr(type='smoke')
+ @test.idempotent_id('16459776-5da2-4634-bce4-4b55ee3ec188')
def test_create_security_group_rule_with_remote_ip_prefix(self):
# Verify creating security group rule with remote_ip_prefix works
sg1_body, _ = self._create_security_group()
@@ -213,6 +220,7 @@
remote_ip_prefix=ip_prefix)
@test.attr(type='smoke')
+ @test.idempotent_id('0a307599-6655-4220-bebc-fd70c64f2290')
def test_create_security_group_rule_with_protocol_integer_value(self):
# Verify creating security group rule with the
# protocol as integer value
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index fb51e30..97c0592 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -15,16 +15,17 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base_security_groups as base
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class NegativeSecGroupTest(base.BaseSecGroupTest):
- _interface = 'json'
+
_tenant_network_cidr = CONF.network.tenant_network_cidr
@classmethod
@@ -35,38 +36,43 @@
raise cls.skipException(msg)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('424fd5c3-9ddc-486a-b45f-39bf0c820fc6')
def test_show_non_existent_security_group(self):
non_exist_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound, self.client.show_security_group,
+ self.assertRaises(lib_exc.NotFound, self.client.show_security_group,
non_exist_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4c094c09-000b-4e41-8100-9617600c02a6')
def test_show_non_existent_security_group_rule(self):
non_exist_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.show_security_group_rule,
non_exist_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1f1bb89d-5664-4956-9fcd-83ee0fa603df')
def test_delete_non_existent_security_group(self):
non_exist_id = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_security_group,
non_exist_id
)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('981bdc22-ce48-41ed-900a-73148b583958')
def test_create_security_group_rule_with_bad_protocol(self):
group_create_body, _ = self._create_security_group()
# Create rule with bad protocol name
pname = 'bad_protocol_name'
self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol=pname, direction='ingress', ethertype=self.ethertype)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5f8daf69-3c5f-4aaa-88c9-db1d66f68679')
def test_create_security_group_rule_with_bad_remote_ip_prefix(self):
group_create_body, _ = self._create_security_group()
@@ -74,12 +80,13 @@
prefix = ['192.168.1./24', '192.168.1.1/33', 'bad_prefix', '256']
for remote_ip_prefix in prefix:
self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol='tcp', direction='ingress', ethertype=self.ethertype,
remote_ip_prefix=remote_ip_prefix)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('4bf786fd-2f02-443c-9716-5b98e159a49a')
def test_create_security_group_rule_with_non_existent_remote_groupid(self):
group_create_body, _ = self._create_security_group()
non_exist_id = str(uuid.uuid4())
@@ -88,12 +95,13 @@
group_ids = ['bad_group_id', non_exist_id]
for remote_group_id in group_ids:
self.assertRaises(
- exceptions.NotFound, self.client.create_security_group_rule,
+ lib_exc.NotFound, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol='tcp', direction='ingress', ethertype=self.ethertype,
remote_group_id=remote_group_id)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('b5c4b247-6b02-435b-b088-d10d45650881')
def test_create_security_group_rule_with_remote_ip_and_group(self):
sg1_body, _ = self._create_security_group()
sg2_body, _ = self._create_security_group()
@@ -101,24 +109,26 @@
# Create rule specifying both remote_ip_prefix and remote_group_id
prefix = self._tenant_network_cidr
self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=sg1_body['security_group']['id'],
protocol='tcp', direction='ingress',
ethertype=self.ethertype, remote_ip_prefix=prefix,
remote_group_id=sg2_body['security_group']['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5666968c-fff3-40d6-9efc-df1c8bd01abb')
def test_create_security_group_rule_with_bad_ethertype(self):
group_create_body, _ = self._create_security_group()
# Create rule with bad ethertype
ethertype = 'bad_ethertype'
self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol='udp', direction='ingress', ethertype=ethertype)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0d9c7791-f2ad-4e2f-ac73-abf2373b0d2d')
def test_create_security_group_rule_with_invalid_ports(self):
group_create_body, _ = self._create_security_group()
@@ -130,7 +140,7 @@
(-16, 65536, 'Invalid value for port')]
for pmin, pmax, msg in states:
ex = self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol='tcp', port_range_min=pmin, port_range_max=pmax,
direction='ingress', ethertype=self.ethertype)
@@ -142,21 +152,23 @@
(300, 1, 'Invalid value for ICMP type')]
for pmin, pmax, msg in states:
ex = self.assertRaises(
- exceptions.BadRequest, self.client.create_security_group_rule,
+ lib_exc.BadRequest, self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
protocol='icmp', port_range_min=pmin, port_range_max=pmax,
direction='ingress', ethertype=self.ethertype)
self.assertIn(msg, str(ex))
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('2323061e-9fbf-4eb0-b547-7e8fafc90849')
def test_create_additional_default_security_group_fails(self):
# Create security group named 'default', it should be failed.
name = 'default'
- self.assertRaises(exceptions.Conflict,
+ self.assertRaises(lib_exc.Conflict,
self.client.create_security_group,
name=name)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('8fde898f-ce88-493b-adc9-4e4692879fc5')
def test_create_duplicate_security_group_rule_fails(self):
# Create duplicate security group rule, it should fail.
body, _ = self._create_security_group()
@@ -175,16 +187,17 @@
# Try creating the same security group rule, it should fail
self.assertRaises(
- exceptions.Conflict, self.client.create_security_group_rule,
+ lib_exc.Conflict, self.client.create_security_group_rule,
security_group_id=body['security_group']['id'],
protocol='tcp', direction='ingress', ethertype=self.ethertype,
port_range_min=min_port, port_range_max=max_port)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('be308db6-a7cf-4d5c-9baf-71bafd73f35e')
def test_create_security_group_rule_with_non_existent_security_group(self):
# Create security group rules with not existing security group.
non_existent_sg = str(uuid.uuid4())
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.create_security_group_rule,
security_group_id=non_existent_sg,
direction='ingress', ethertype=self.ethertype)
@@ -195,6 +208,7 @@
_tenant_network_cidr = CONF.network.tenant_network_v6_cidr
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7607439c-af73-499e-bf64-f687fd12a842')
def test_create_security_group_rule_wrong_ip_prefix_version(self):
group_create_body, _ = self._create_security_group()
@@ -205,7 +219,7 @@
'ip_prefix': CONF.network.tenant_network_v6_cidr})
for pair in pairs:
self.assertRaisesRegexp(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
"Conflicting value ethertype",
self.client.create_security_group_rule,
security_group_id=group_create_body['security_group']['id'],
diff --git a/tempest/api/network/test_service_type_management.py b/tempest/api/network/test_service_type_management.py
index 0492fe3..a1e4136 100644
--- a/tempest/api/network/test_service_type_management.py
+++ b/tempest/api/network/test_service_type_management.py
@@ -17,7 +17,6 @@
class ServiceTypeManagementTestJSON(base.BaseNetworkTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -28,6 +27,7 @@
@decorators.skip_because(bug="1400370")
@test.attr(type='smoke')
+ @test.idempotent_id('2cbbeea9-f010-40f6-8df5-4eaa0c918ea6')
def test_service_provider_list(self):
body = self.client.list_service_providers()
self.assertIsInstance(body['service_providers'], list)
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index 56e1a05..ebf31d3 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -13,17 +13,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
class VPNaaSTestJSON(base.BaseAdminNetworkTest):
- _interface = 'json'
"""
Tests the following operations in the Neutron API using the REST client for
@@ -74,7 +74,7 @@
try:
self.client.delete_ipsecpolicy(ipsec_policy_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
def _assertExpected(self, expected, actual):
@@ -101,6 +101,7 @@
return body['network']['tenant_id']
@test.attr(type='smoke')
+ @test.idempotent_id('14311574-0737-4e53-ac05-f7ae27742eed')
def test_admin_create_ipsec_policy_for_tenant(self):
tenant_id = self._get_tenant_id()
# Create IPSec policy for the newly created tenant
@@ -118,6 +119,7 @@
self.assertIn(ipsecpolicy['id'], ipsecpolicies)
@test.attr(type='smoke')
+ @test.idempotent_id('b62acdc6-0c53-4d84-84aa-859b22b79799')
def test_admin_create_vpn_service_for_tenant(self):
tenant_id = self._get_tenant_id()
@@ -143,6 +145,7 @@
self.assertIn(vpnservice['id'], vpn_services)
@test.attr(type='smoke')
+ @test.idempotent_id('58cc4a1c-443b-4f39-8fb6-c19d39f343ab')
def test_admin_create_ike_policy_for_tenant(self):
tenant_id = self._get_tenant_id()
@@ -163,6 +166,7 @@
self.assertIn(ikepolicy['id'], ikepolicies)
@test.attr(type='smoke')
+ @test.idempotent_id('de5bb04c-3a1f-46b1-b329-7a8abba5c7f1')
def test_list_vpn_services(self):
# Verify the VPN service exists in the list of all VPN services
body = self.client.list_vpnservices()
@@ -170,6 +174,7 @@
self.assertIn(self.vpnservice['id'], [v['id'] for v in vpnservices])
@test.attr(type='smoke')
+ @test.idempotent_id('aacb13b1-fdc7-41fd-bab2-32621aee1878')
def test_create_update_delete_vpn_service(self):
# Creates a VPN service and sets up deletion
network1 = self.create_network()
@@ -196,6 +201,7 @@
# should be "ACTIVE" not "PENDING*"
@test.attr(type='smoke')
+ @test.idempotent_id('0dedfc1d-f8ee-4e2a-bfd4-7997b9dc17ff')
def test_show_vpn_service(self):
# Verifies the details of a vpn service
body = self.client.show_vpnservice(self.vpnservice['id'])
@@ -212,6 +218,7 @@
self.assertIn(vpnservice['status'], valid_status)
@test.attr(type='smoke')
+ @test.idempotent_id('e0fb6200-da3d-4869-8340-a8c1956ca618')
def test_list_ike_policies(self):
# Verify the ike policy exists in the list of all IKE policies
body = self.client.list_ikepolicies()
@@ -219,6 +226,7 @@
self.assertIn(self.ikepolicy['id'], [i['id'] for i in ikepolicies])
@test.attr(type='smoke')
+ @test.idempotent_id('d61f29a5-160c-487d-bc0d-22e32e731b44')
def test_create_update_delete_ike_policy(self):
# Creates a IKE policy
name = data_utils.rand_name('ike-policy')
@@ -253,6 +261,7 @@
self.assertNotIn(ike_policy['id'], ikepolicies)
@test.attr(type='smoke')
+ @test.idempotent_id('b5fcf3a3-9407-452d-b8a8-e7c6c32baea8')
def test_show_ike_policy(self):
# Verifies the details of a ike policy
body = self.client.show_ikepolicy(self.ikepolicy['id'])
@@ -275,6 +284,7 @@
ikepolicy['ike_version'])
@test.attr(type='smoke')
+ @test.idempotent_id('19ea0a2f-add9-44be-b732-ffd8a7b42f37')
def test_list_ipsec_policies(self):
# Verify the ipsec policy exists in the list of all ipsec policies
body = self.client.list_ipsecpolicies()
@@ -282,6 +292,7 @@
self.assertIn(self.ipsecpolicy['id'], [i['id'] for i in ipsecpolicies])
@test.attr(type='smoke')
+ @test.idempotent_id('9c1701c9-329a-4e5d-930a-1ead1b3f86ad')
def test_create_update_delete_ipsec_policy(self):
# Creates an ipsec policy
ipsec_policy_body = {'name': data_utils.rand_name('ipsec-policy'),
@@ -304,10 +315,11 @@
self._assertExpected(new_ipsec, updated_ipsec_policy)
# Verification of ipsec policy delete
self.client.delete_ipsecpolicy(ipsecpolicy['id'])
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.delete_ipsecpolicy, ipsecpolicy['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('601f8a05-9d3c-4539-a400-1c4b3a21b03b')
def test_show_ipsec_policy(self):
# Verifies the details of an ipsec policy
body = self.client.show_ipsecpolicy(self.ipsecpolicy['id'])
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 36c9f5a..6a025d9 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -13,13 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
from tempest.api.identity import base
from tempest import clients
from tempest.common import credentials
from tempest.common import custom_matchers
from tempest import config
-from tempest import exceptions
import tempest.test
CONF = config.CONF
@@ -28,21 +28,31 @@
class BaseObjectTest(tempest.test.BaseTestCase):
@classmethod
- def resource_setup(cls):
- cls.set_network_resources()
- super(BaseObjectTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(BaseObjectTest, cls).skip_checks()
if not CONF.service_available.swift:
skip_msg = ("%s skipped as swift is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources()
+ super(BaseObjectTest, cls).setup_credentials()
+
cls.isolated_creds = credentials.get_isolated_credentials(
cls.__name__, network_resources=cls.network_resources)
# Get isolated creds for normal user
cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
# Get isolated creds for admin user
cls.os_admin = clients.Manager(cls.isolated_creds.get_admin_creds())
+ cls.data = SwiftDataGenerator(cls.os_admin.identity_client)
# Get isolated creds for alt user
cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
+ @classmethod
+ def setup_clients(cls):
+ super(BaseObjectTest, cls).setup_clients()
+
cls.object_client = cls.os.object_client
cls.container_client = cls.os.container_client
cls.account_client = cls.os.account_client
@@ -52,6 +62,10 @@
cls.container_client_alt = cls.os_alt.container_client
cls.identity_client_alt = cls.os_alt.identity_client
+ @classmethod
+ def resource_setup(cls):
+ super(BaseObjectTest, cls).resource_setup()
+
# Make sure we get fresh auth data after assigning swift role
cls.object_client.auth_provider.clear_auth()
cls.container_client.auth_provider.clear_auth()
@@ -59,8 +73,6 @@
cls.object_client_alt.auth_provider.clear_auth()
cls.container_client_alt.auth_provider.clear_auth()
- cls.data = SwiftDataGenerator(cls.identity_admin_client)
-
@classmethod
def resource_cleanup(cls):
cls.data.teardown_all()
@@ -93,10 +105,10 @@
for obj in objlist:
try:
object_client.delete_object(cont, obj['name'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
container_client.delete_container(cont)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
def assertHeaders(self, resp, target, method):
@@ -126,7 +138,7 @@
return next(r['id'] for r in roles if r['name'] == role_name)
except StopIteration:
msg = "Role name '%s' is not found" % role_name
- raise exceptions.NotFound(msg)
+ raise lib_exc.NotFound(msg)
def _assign_role(self, role_id):
self.client.assign_user_role(self.tenant['id'],
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index 31a80cf..54c87d7 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -66,6 +66,7 @@
self.assertNotIn(container_name, body)
@test.attr(type='gate')
+ @test.idempotent_id('a407de51-1983-47cc-9f14-47c2b059413c')
@test.requires_ext(extension='bulk', service='object')
def test_extract_archive(self):
# Test bulk operation of file upload with an archived file
@@ -102,6 +103,7 @@
self.assertIn(object_name, [c['name'] for c in contents_list])
@test.attr(type='gate')
+ @test.idempotent_id('c075e682-0d2a-43b2-808d-4116200d736d')
@test.requires_ext(extension='bulk', service='object')
def test_bulk_delete(self):
# Test bulk operation of deleting multiple files
@@ -129,6 +131,7 @@
self._check_contents_deleted(container_name)
@test.attr(type='gate')
+ @test.idempotent_id('dbea2bcb-efbb-4674-ac8a-a5a0e33d1d79')
@test.requires_ext(extension='bulk', service='object')
def test_bulk_delete_by_POST(self):
# Test bulk operation of deleting multiple files
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 1832b37..9b379f4 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -26,15 +24,17 @@
class AccountQuotasTest(base.BaseObjectTest):
@classmethod
+ def setup_credentials(cls):
+ super(AccountQuotasTest, cls).setup_credentials()
+ cls.data.setup_test_user(reseller=True)
+ cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
+
+ @classmethod
def resource_setup(cls):
super(AccountQuotasTest, cls).resource_setup()
cls.container_name = data_utils.rand_name(name="TestContainer")
cls.container_client.create_container(cls.container_name)
- cls.data.setup_test_user(reseller=True)
-
- cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
-
# Retrieve a ResellerAdmin auth data and use it to set a quota
# on the client's account
cls.reselleradmin_auth_data = \
@@ -76,6 +76,7 @@
super(AccountQuotasTest, cls).resource_cleanup()
@test.attr(type="smoke")
+ @test.idempotent_id('a22ef352-a342-4587-8f47-3bbdb5b039c4')
@test.requires_ext(extension='account_quotas', service='object')
def test_upload_valid_object(self):
object_name = data_utils.rand_name(name="TestObject")
@@ -86,6 +87,7 @@
self.assertHeaders(resp, 'Object', 'PUT')
@test.attr(type=["smoke"])
+ @test.idempotent_id('63f51f9f-5f1d-4fc6-b5be-d454d70949d6')
@test.requires_ext(extension='account_quotas', service='object')
def test_admin_modify_quota(self):
"""Test that the ResellerAdmin is able to modify and remove the quota
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 5a0be54..7d4008c 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -15,12 +13,12 @@
# under the License.
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
from tempest.api.object_storage import base
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -29,15 +27,17 @@
class AccountQuotasNegativeTest(base.BaseObjectTest):
@classmethod
+ def setup_credentials(cls):
+ super(AccountQuotasNegativeTest, cls).setup_credentials()
+ cls.data.setup_test_user(reseller=True)
+ cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
+
+ @classmethod
def resource_setup(cls):
super(AccountQuotasNegativeTest, cls).resource_setup()
cls.container_name = data_utils.rand_name(name="TestContainer")
cls.container_client.create_container(cls.container_name)
- cls.data.setup_test_user(reseller=True)
-
- cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
-
# Retrieve a ResellerAdmin auth data and use it to set a quota
# on the client's account
cls.reselleradmin_auth_data = \
@@ -78,6 +78,7 @@
super(AccountQuotasNegativeTest, cls).resource_cleanup()
@test.attr(type=["negative", "smoke"])
+ @test.idempotent_id('d1dc5076-555e-4e6d-9697-28f1fe976324')
@test.requires_ext(extension='account_quotas', service='object')
def test_user_modify_quota(self):
"""Test that a user is not able to modify or remove a quota on
@@ -85,21 +86,22 @@
"""
# Not able to remove quota
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.account_client.create_account_metadata,
{"Quota-Bytes": ""})
# Not able to modify quota
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.account_client.create_account_metadata,
{"Quota-Bytes": "100"})
@test.attr(type=["negative", "smoke"])
@decorators.skip_because(bug="1310597")
+ @test.idempotent_id('cf9e21f5-3aa4-41b1-9462-28ac550d8d3f')
@test.requires_ext(extension='account_quotas', service='object')
def test_upload_large_object(self):
object_name = data_utils.rand_name(name="TestObject")
data = data_utils.arbitrary_string(30)
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.object_client.create_object,
self.container_name, object_name, data)
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 2bc4f59..63d0425 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -46,6 +46,7 @@
super(AccountTest, cls).resource_cleanup()
@test.attr(type='smoke')
+ @test.idempotent_id('3499406a-ae53-4f8c-b43a-133d4dc6fe3f')
def test_list_containers(self):
# list of all containers should not be empty
resp, container_list = self.account_client.list_account_containers()
@@ -56,6 +57,7 @@
self.assertIn(container_name, container_list)
@test.attr(type='smoke')
+ @test.idempotent_id('884ec421-fbad-4fcc-916b-0580f2699565')
def test_list_no_containers(self):
# List request to empty account
@@ -87,6 +89,7 @@
self.assertEqual(len(container_list), 0)
@test.attr(type='smoke')
+ @test.idempotent_id('1c7efa35-e8a2-4b0b-b5ff-862c7fd83704')
def test_list_containers_with_format_json(self):
# list containers setting format parameter to 'json'
params = {'format': 'json'}
@@ -99,6 +102,7 @@
self.assertTrue([c['bytes'] for c in container_list])
@test.attr(type='smoke')
+ @test.idempotent_id('4477b609-1ca6-4d4b-b25d-ad3f01086089')
def test_list_containers_with_format_xml(self):
# list containers setting format parameter to 'xml'
params = {'format': 'xml'}
@@ -114,6 +118,7 @@
self.assertEqual(container_list.find(".//bytes").tag, 'bytes')
@test.attr(type='smoke')
+ @test.idempotent_id('6eb04a6a-4860-4e31-ba91-ea3347d76b58')
@testtools.skipIf(
not CONF.object_storage_feature_enabled.discoverability,
'Discoverability function is disabled')
@@ -123,6 +128,7 @@
self.assertThat(resp, custom_matchers.AreAllWellFormatted())
@test.attr(type='smoke')
+ @test.idempotent_id('5cfa4ab2-4373-48dd-a41f-a532b12b08b2')
def test_list_containers_with_limit(self):
# list containers one of them, half of them then all of them
for limit in (1, self.containers_count / 2, self.containers_count):
@@ -134,6 +140,7 @@
self.assertEqual(len(container_list), limit)
@test.attr(type='smoke')
+ @test.idempotent_id('638f876d-6a43-482a-bbb3-0840bca101c6')
def test_list_containers_with_marker(self):
# list containers using marker param
# first expect to get 0 container as we specified last
@@ -154,6 +161,7 @@
self.assertEqual(len(container_list), self.containers_count / 2 - 1)
@test.attr(type='smoke')
+ @test.idempotent_id('5ca164e4-7bde-43fa-bafb-913b53b9e786')
def test_list_containers_with_end_marker(self):
# list containers using end_marker param
# first expect to get 0 container as we specified first container as
@@ -172,6 +180,7 @@
self.assertEqual(len(container_list), self.containers_count / 2)
@test.attr(type='smoke')
+ @test.idempotent_id('ac8502c2-d4e4-4f68-85a6-40befea2ef5e')
def test_list_containers_with_marker_and_end_marker(self):
# list containers combining marker and end_marker param
params = {'marker': self.containers[0],
@@ -182,6 +191,7 @@
self.assertEqual(len(container_list), self.containers_count - 2)
@test.attr(type='smoke')
+ @test.idempotent_id('f7064ae8-dbcc-48da-b594-82feef6ea5af')
def test_list_containers_with_limit_and_marker(self):
# list containers combining marker and limit param
# result are always limitated by the limit whatever the marker
@@ -196,6 +206,7 @@
self.assertTrue(len(container_list) <= limit, str(container_list))
@test.attr(type='smoke')
+ @test.idempotent_id('888a3f0e-7214-4806-8e50-5e0c9a69bb5e')
def test_list_containers_with_limit_and_end_marker(self):
# list containers combining limit and end_marker param
limit = random.randint(1, self.containers_count)
@@ -208,6 +219,7 @@
min(limit, self.containers_count / 2))
@test.attr(type='smoke')
+ @test.idempotent_id('8cf98d9c-e3a0-4e44-971b-c87656fdddbd')
def test_list_containers_with_limit_and_marker_and_end_marker(self):
# list containers combining limit, marker and end_marker param
limit = random.randint(1, self.containers_count)
@@ -221,6 +233,7 @@
min(limit, self.containers_count - 2))
@test.attr(type='smoke')
+ @test.idempotent_id('4894c312-6056-4587-8d6f-86ffbf861f80')
def test_list_account_metadata(self):
# list all account metadata
@@ -236,6 +249,7 @@
self.account_client.delete_account_metadata(metadata)
@test.attr(type='smoke')
+ @test.idempotent_id('b904c2e3-24c2-4dba-ad7d-04e90a761be5')
def test_list_no_account_metadata(self):
# list no account metadata
resp, _ = self.account_client.list_account_metadata()
@@ -243,6 +257,7 @@
self.assertNotIn('x-account-meta-', str(resp))
@test.attr(type='smoke')
+ @test.idempotent_id('e2a08b5f-3115-4768-a3ee-d4287acd6c08')
def test_update_account_metadata_with_create_metadata(self):
# add metadata to account
metadata = {'test-account-meta1': 'Meta1'}
@@ -257,6 +272,7 @@
self.account_client.delete_account_metadata(metadata)
@test.attr(type='smoke')
+ @test.idempotent_id('9f60348d-c46f-4465-ae06-d51dbd470953')
def test_update_account_metadata_with_delete_matadata(self):
# delete metadata from account
metadata = {'test-account-meta1': 'Meta1'}
@@ -268,6 +284,7 @@
self.assertNotIn('x-account-meta-test-account-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('64fd53f3-adbd-4639-af54-436e4982dbfb')
def test_update_account_metadata_with_create_matadata_key(self):
# if the value of metadata is not set, the metadata is not
# registered at a server
@@ -279,6 +296,7 @@
self.assertNotIn('x-account-meta-test-account-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('d4d884d3-4696-4b85-bc98-4f57c4dd2bf1')
def test_update_account_metadata_with_delete_matadata_key(self):
# Although the value of metadata is not set, the feature of
# deleting metadata is valid
@@ -292,6 +310,7 @@
self.assertNotIn('x-account-meta-test-account-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('8e5fc073-59b9-42ee-984a-29ed11b2c749')
def test_update_account_metadata_with_create_and_delete_metadata(self):
# Send a request adding and deleting metadata requests simultaneously
metadata_1 = {'test-account-meta1': 'Meta1'}
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index ef04387..f329675 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -14,15 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest import clients
-from tempest import exceptions
from tempest import test
class AccountNegativeTest(base.BaseObjectTest):
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
def test_list_containers_with_non_authorized_user(self):
# list containers using non-authorized user
@@ -44,6 +44,6 @@
params = {'format': 'json'}
# list containers with non-authorized user token
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.account_client.list_account_containers,
params=params)
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 205bc91..6368bec 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -20,12 +20,17 @@
class ObjectTestACLs(base.BaseObjectTest):
+
+ @classmethod
+ def setup_credentials(cls):
+ super(ObjectTestACLs, cls).setup_credentials()
+ cls.data.setup_test_user()
+ cls.test_os = clients.Manager(cls.data.test_credentials)
+
@classmethod
def resource_setup(cls):
super(ObjectTestACLs, cls).resource_setup()
- cls.data.setup_test_user()
- test_os = clients.Manager(cls.data.test_credentials)
- cls.test_auth_data = test_os.auth_provider.auth_data
+ cls.test_auth_data = cls.test_os.auth_provider.auth_data
def setUp(self):
super(ObjectTestACLs, self).setUp()
@@ -37,6 +42,7 @@
super(ObjectTestACLs, self).tearDown()
@test.attr(type='smoke')
+ @test.idempotent_id('a3270f3f-7640-4944-8448-c7ea783ea5b6')
def test_read_object_with_rights(self):
# attempt to read object using authorized user
# update X-Container-Read metadata ACL
@@ -61,6 +67,7 @@
self.assertHeaders(resp, 'Object', 'GET')
@test.attr(type='smoke')
+ @test.idempotent_id('aa58bfa5-40d9-4bc3-82b4-d07f4a9e392a')
def test_write_object_with_rights(self):
# attempt to write object using authorized user
# update X-Container-Write metadata ACL
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 138d25a..5892340 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -14,20 +12,26 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest import clients
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ObjectACLsNegativeTest(base.BaseObjectTest):
+
+ @classmethod
+ def setup_credentials(cls):
+ super(ObjectACLsNegativeTest, cls).setup_credentials()
+ cls.data.setup_test_user()
+ cls.test_os = clients.Manager(cls.data.test_credentials)
+
@classmethod
def resource_setup(cls):
super(ObjectACLsNegativeTest, cls).resource_setup()
- cls.data.setup_test_user()
- test_os = clients.Manager(cls.data.test_credentials)
- cls.test_auth_data = test_os.auth_provider.auth_data
+ cls.test_auth_data = cls.test_os.auth_provider.auth_data
def setUp(self):
super(ObjectACLsNegativeTest, self).setUp()
@@ -39,6 +43,7 @@
super(ObjectACLsNegativeTest, self).tearDown()
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('af587587-0c24-4e15-9822-8352ce711013')
def test_write_object_without_using_creds(self):
# trying to create object with empty headers
# X-Auth-Token is not provided
@@ -47,11 +52,12 @@
request_part='headers',
auth_data=None
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.create_object,
self.container_name, object_name, 'data', headers={})
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('af85af0b-a025-4e72-a90e-121babf55720')
def test_delete_object_without_using_creds(self):
# create object
object_name = data_utils.rand_name(name='Object')
@@ -63,11 +69,12 @@
request_part='headers',
auth_data=None
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.delete_object,
self.container_name, object_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('63d84e37-55a6-42e2-9e5f-276e60e26a00')
def test_write_object_with_non_authorized_user(self):
# attempt to upload another file using non-authorized user
# User provided token is forbidden. ACL are not set
@@ -77,11 +84,12 @@
request_part='headers',
auth_data=self.test_auth_data
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.create_object,
self.container_name, object_name, 'data', headers={})
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('abf63359-be52-4feb-87dd-447689fc77fd')
def test_read_object_with_non_authorized_user(self):
# attempt to read object using non-authorized user
# User provided token is forbidden. ACL are not set
@@ -94,11 +102,12 @@
request_part='headers',
auth_data=self.test_auth_data
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.get_object,
self.container_name, object_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('7343ac3d-cfed-4198-9bb0-00149741a492')
def test_delete_object_with_non_authorized_user(self):
# attempt to delete object using non-authorized user
# User provided token is forbidden. ACL are not set
@@ -111,11 +120,12 @@
request_part='headers',
auth_data=self.test_auth_data
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.delete_object,
self.container_name, object_name)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('9ed01334-01e9-41ea-87ea-e6f465582823')
def test_read_object_without_rights(self):
# attempt to read object using non-authorized user
# update X-Container-Read metadata ACL
@@ -134,11 +144,12 @@
request_part='headers',
auth_data=self.test_auth_data
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.get_object,
self.container_name, object_name)
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('a3a585a7-d8cf-4b65-a1a0-edc2b1204f85')
def test_write_object_without_rights(self):
# attempt to write object using non-authorized user
# update X-Container-Write metadata ACL
@@ -153,12 +164,13 @@
auth_data=self.test_auth_data
)
object_name = data_utils.rand_name(name='Object')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.create_object,
self.container_name,
object_name, 'data', headers={})
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('8ba512ad-aa6e-444e-b882-2906a0ea2052')
def test_write_object_without_write_rights(self):
# attempt to write object using non-authorized user
# update X-Container-Read and X-Container-Write metadata ACL
@@ -175,12 +187,13 @@
auth_data=self.test_auth_data
)
object_name = data_utils.rand_name(name='Object')
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.create_object,
self.container_name,
object_name, 'data', headers={})
@test.attr(type=['negative', 'smoke'])
+ @test.idempotent_id('b4e366f8-f185-47ab-b789-df4416f9ecdb')
def test_delete_object_without_write_rights(self):
# attempt to delete object using non-authorized user
# update X-Container-Read and X-Container-Write metadata ACL
@@ -201,7 +214,7 @@
request_part='headers',
auth_data=self.test_auth_data
)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.delete_object,
self.container_name,
object_name)
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 46944ed..c78b4c3 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -13,10 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -50,6 +51,7 @@
self.delete_containers([self.container_name])
super(ContainerQuotasTest, self).tearDown()
+ @test.idempotent_id('9a0fb034-86af-4df0-86fa-f8bd7db21ae0')
@test.requires_ext(extension='container_quotas', service='object')
@test.attr(type="smoke")
def test_upload_valid_object(self):
@@ -66,6 +68,7 @@
nafter = self._get_bytes_used()
self.assertEqual(nbefore + len(data), nafter)
+ @test.idempotent_id('22eeeb2b-3668-4160-baef-44790f65a5a0')
@test.requires_ext(extension='container_quotas', service='object')
@test.attr(type="smoke")
def test_upload_large_object(self):
@@ -75,13 +78,14 @@
nbefore = self._get_bytes_used()
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.object_client.create_object,
self.container_name, object_name, data)
nafter = self._get_bytes_used()
self.assertEqual(nbefore, nafter)
+ @test.idempotent_id('3a387039-697a-44fc-a9c0-935de31f426b')
@test.requires_ext(extension='container_quotas', service='object')
@test.attr(type="smoke")
def test_upload_too_many_objects(self):
@@ -93,7 +97,7 @@
nbefore = self._get_object_count()
self.assertEqual(nbefore, QUOTA_COUNT)
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.object_client.create_object,
self.container_name, "OverQuotaObject", "")
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index fe06fd0..54da0d1 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -47,6 +47,7 @@
return object_name
@test.attr(type='smoke')
+ @test.idempotent_id('92139d73-7819-4db1-85f8-3f2f22a8d91f')
def test_create_container(self):
container_name = data_utils.rand_name(name='TestContainer')
resp, body = self.container_client.create_container(container_name)
@@ -54,6 +55,7 @@
self.assertHeaders(resp, 'Container', 'PUT')
@test.attr(type='smoke')
+ @test.idempotent_id('49f866ed-d6af-4395-93e7-4187eb56d322')
def test_create_container_overwrite(self):
# overwrite container with the same name
container_name = data_utils.rand_name(name='TestContainer')
@@ -64,6 +66,7 @@
self.assertHeaders(resp, 'Container', 'PUT')
@test.attr(type='smoke')
+ @test.idempotent_id('c2ac4d59-d0f5-40d5-ba19-0635056d48cd')
def test_create_container_with_metadata_key(self):
# create container with the blank value of metadata
container_name = data_utils.rand_name(name='TestContainer')
@@ -81,6 +84,7 @@
self.assertNotIn('x-container-meta-test-container-meta', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('e1e8df32-7b22-44e1-aa08-ccfd8d446b58')
def test_create_container_with_metadata_value(self):
# create container with metadata value
container_name = data_utils.rand_name(name='TestContainer')
@@ -99,6 +103,7 @@
metadata['test-container-meta'])
@test.attr(type='smoke')
+ @test.idempotent_id('24d16451-1c0c-4e4f-b59c-9840a3aba40e')
def test_create_container_with_remove_metadata_key(self):
# create container with the blank value of remove metadata
container_name = data_utils.rand_name(name='TestContainer')
@@ -119,6 +124,7 @@
self.assertNotIn('x-container-meta-test-container-meta', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('8a21ebad-a5c7-4e29-b428-384edc8cd156')
def test_create_container_with_remove_metadata_value(self):
# create container with remove metadata
container_name = data_utils.rand_name(name='TestContainer')
@@ -137,6 +143,7 @@
self.assertNotIn('x-container-meta-test-container-meta', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('95d3a249-b702-4082-a2c4-14bb860cf06a')
def test_delete_container(self):
# create a container
container_name = self._create_container()
@@ -146,6 +153,7 @@
self.containers.remove(container_name)
@test.attr(type='smoke')
+ @test.idempotent_id('312ff6bd-5290-497f-bda1-7c5fec6697ab')
def test_list_container_contents(self):
# get container contents list
container_name = self._create_container()
@@ -157,6 +165,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('4646ac2d-9bfb-4c7d-a3c5-0f527402b3df')
def test_list_container_contents_with_no_object(self):
# get empty container contents list
container_name = self._create_container()
@@ -167,6 +176,7 @@
self.assertEqual('', object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('fe323a32-57b9-4704-a996-2e68f83b09bc')
def test_list_container_contents_with_delimiter(self):
# get container contents list using delimiter param
container_name = self._create_container()
@@ -181,6 +191,7 @@
self.assertEqual(object_name.split('/')[0], object_list.strip('/\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('55b4fa5c-e12e-4ca9-8fcf-a79afe118522')
def test_list_container_contents_with_end_marker(self):
# get container contents list using end_marker param
container_name = self._create_container()
@@ -194,6 +205,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('196f5034-6ab0-4032-9da9-a937bbb9fba9')
def test_list_container_contents_with_format_json(self):
# get container contents list using format_json param
container_name = self._create_container()
@@ -213,6 +225,7 @@
self.assertTrue([c['last_modified'] for c in object_list])
@test.attr(type='smoke')
+ @test.idempotent_id('655a53ca-4d15-408c-a377-f4c6dbd0a1fa')
def test_list_container_contents_with_format_xml(self):
# get container contents list using format_xml param
container_name = self._create_container()
@@ -237,6 +250,7 @@
'last_modified')
@test.attr(type='smoke')
+ @test.idempotent_id('297ec38b-2b61-4ff4-bcd1-7fa055e97b61')
def test_list_container_contents_with_limit(self):
# get container contents list using limit param
container_name = self._create_container()
@@ -250,6 +264,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('c31ddc63-2a58-4f6b-b25c-94d2937e6867')
def test_list_container_contents_with_marker(self):
# get container contents list using marker param
container_name = self._create_container()
@@ -263,6 +278,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('58ca6cc9-6af0-408d-aaec-2a6a7b2f0df9')
def test_list_container_contents_with_path(self):
# get container contents list using path param
container_name = self._create_container()
@@ -277,6 +293,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('77e742c7-caf2-4ec9-8aa4-f7d509a3344c')
def test_list_container_contents_with_prefix(self):
# get container contents list using prefix param
container_name = self._create_container()
@@ -291,6 +308,7 @@
self.assertEqual(object_name, object_list.strip('\n'))
@test.attr(type='smoke')
+ @test.idempotent_id('96e68f0e-19ec-4aa2-86f3-adc6a45e14dd')
def test_list_container_metadata(self):
# List container metadata
container_name = self._create_container()
@@ -307,6 +325,7 @@
self.assertEqual(resp['x-container-meta-name'], metadata['name'])
@test.attr(type='smoke')
+ @test.idempotent_id('a2faf936-6b13-4f8d-92a2-c2278355821e')
def test_list_no_container_metadata(self):
# HEAD container without metadata
container_name = self._create_container()
@@ -317,6 +336,7 @@
self.assertNotIn('x-container-meta-', str(resp))
@test.attr(type='smoke')
+ @test.idempotent_id('cf19bc0b-7e16-4a5a-aaed-cb0c2fe8deef')
def test_update_container_metadata_with_create_and_delete_matadata(self):
# Send one request of adding and deleting metadata
container_name = data_utils.rand_name(name='TestContainer')
@@ -340,6 +360,7 @@
metadata_2['test-container-meta2'])
@test.attr(type='smoke')
+ @test.idempotent_id('2ae5f295-4bf1-4e04-bfad-21e54b62cec5')
def test_update_container_metadata_with_create_metadata(self):
# update container metadata using add metadata
container_name = self._create_container()
@@ -357,6 +378,7 @@
metadata['test-container-meta1'])
@test.attr(type='smoke')
+ @test.idempotent_id('3a5ce7d4-6e4b-47d0-9d87-7cd42c325094')
def test_update_container_metadata_with_delete_metadata(self):
# update container metadata using delete metadata
container_name = data_utils.rand_name(name='TestContainer')
@@ -375,6 +397,7 @@
self.assertNotIn('x-container-meta-test-container-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('31f40a5f-6a52-4314-8794-cd89baed3040')
def test_update_container_metadata_with_create_matadata_key(self):
# update container metadata with a blenk value of metadata
container_name = self._create_container()
@@ -390,6 +413,7 @@
self.assertNotIn('x-container-meta-test-container-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('a2e36378-6f1f-43f4-840a-ffd9cfd61914')
def test_update_container_metadata_with_delete_metadata_key(self):
# update container metadata with a blank value of matadata
container_name = data_utils.rand_name(name='TestContainer')
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index a8e5f9a..45ecfec 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -14,10 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest.common import custom_matchers
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -50,6 +49,7 @@
cls.delete_containers([cls.container_name])
super(StaticWebTest, cls).resource_cleanup()
+ @test.idempotent_id('c1f055ab-621d-4a6a-831f-846fcb578b8b')
@test.requires_ext(extension='staticweb', service='object')
@test.attr('gate')
def test_web_index(self):
@@ -81,6 +81,7 @@
self.container_name)
self.assertNotIn('x-container-meta-web-index', body)
+ @test.idempotent_id('941814cf-db9e-4b21-8112-2b6d0af10ee5')
@test.requires_ext(extension='staticweb', service='object')
@test.attr('gate')
def test_web_listing(self):
@@ -113,6 +114,7 @@
self.container_name)
self.assertNotIn('x-container-meta-web-listings', body)
+ @test.idempotent_id('bc37ec94-43c8-4990-842e-0e5e02fc8926')
@test.requires_ext(extension='staticweb', service='object')
@test.attr('gate')
def test_web_listing_css(self):
@@ -137,6 +139,7 @@
css = '<link rel="stylesheet" type="text/css" href="listings.css" />'
self.assertIn(css, body)
+ @test.idempotent_id('f18b4bef-212e-45e7-b3ca-59af3a465f82')
@test.requires_ext(extension='staticweb', service='object')
@test.attr('gate')
def test_web_error(self):
@@ -161,5 +164,5 @@
# Request non-existing object
self.assertRaises(
- exceptions.NotFound, self.object_client.get_object,
+ lib_exc.NotFound, self.object_client.get_object,
self.container_name, "notexisting")
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 09b0ce0..71f1275 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -114,6 +114,7 @@
@test.attr(type='slow')
@decorators.skip_because(bug='1317133')
+ @test.idempotent_id('be008325-1bba-4925-b7dd-93b58f22ce9b')
@testtools.skipIf(
not CONF.object_storage_feature_enabled.container_sync,
'Old-style container sync function is disabled')
diff --git a/tempest/api/object_storage/test_container_sync_middleware.py b/tempest/api/object_storage/test_container_sync_middleware.py
index 41509a0..4491a84 100644
--- a/tempest/api/object_storage/test_container_sync_middleware.py
+++ b/tempest/api/object_storage/test_container_sync_middleware.py
@@ -37,6 +37,7 @@
cls.cluster_name = CONF.object_storage.cluster_name
@test.attr(type='slow')
+ @test.idempotent_id('ea4645a1-d147-4976-82f7-e5a7a3065f80')
@test.requires_ext(extension='container_sync', service='object')
def test_container_synchronization(self):
def make_headers(cont, cont_client):
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index 66e8176..9d49a73 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -39,6 +37,7 @@
self.account_client.skip_path()
@test.attr('gate')
+ @test.idempotent_id('d1b8b031-b622-4010-82f9-ff78a9e915c7')
@test.requires_ext(extension='crossdomain', service='object')
def test_get_crossdomain_policy(self):
resp, body = self.account_client.get("crossdomain.xml", {})
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index 53c0347..2ca0a9f 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -22,16 +20,13 @@
class HealthcheckTest(base.BaseObjectTest):
- @classmethod
- def resource_setup(cls):
- super(HealthcheckTest, cls).resource_setup()
-
def setUp(self):
super(HealthcheckTest, self).setUp()
# Turning http://.../v1/foobar into http://.../
self.account_client.skip_path()
@test.attr('gate')
+ @test.idempotent_id('db5723b1-f25c-49a9-bfeb-7b5640caf337')
def test_get_healthcheck(self):
resp, _ = self.account_client.get("healthcheck", {})
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 5fa209d..ac6f49a 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -13,11 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
import time
from tempest.api.object_storage import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -66,10 +66,11 @@
time.sleep(sleepy_time + 3)
# object should not be there anymore
- self.assertRaises(exceptions.NotFound, self.object_client.get_object,
+ self.assertRaises(lib_exc.NotFound, self.object_client.get_object,
self.container_name, self.object_name)
@test.attr(type='gate')
+ @test.idempotent_id('fb024a42-37f3-4ba5-9684-4f40a7910b41')
def test_get_object_after_expiry_time(self):
# the 10s is important, because the get calls can take 3s each
# some times
@@ -77,6 +78,7 @@
self._test_object_expiry(metadata)
@test.attr(type='gate')
+ @test.idempotent_id('e592f18d-679c-48fe-9e36-4be5f47102c5')
def test_get_object_at_expiry_time(self):
metadata = {'X-Delete-At': str(int(time.time()) + 10)}
self._test_object_expiry(metadata)
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 7a9fcf6..3e0fc7b 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Christian Schwede <christian.schwede@enovance.com>
-#
# 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
@@ -106,6 +104,7 @@
content_type = 'multipart/form-data; boundary=%s' % boundary
return body, content_type
+ @test.idempotent_id('80fac02b-6e54-4f7b-be0d-a965b5cbef76')
@test.requires_ext(extension='formpost', service='object')
@test.attr(type='gate')
def test_post_object_using_form(self):
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index 32f5917..d92a2e5 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -1,5 +1,4 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
#
# 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
@@ -18,9 +17,10 @@
import time
import urlparse
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -106,6 +106,7 @@
content_type = 'multipart/form-data; boundary=%s' % boundary
return body, content_type
+ @test.idempotent_id('d3fb3c4d-e627-48ce-9379-a1631f21336d')
@test.requires_ext(extension='formpost', service='object')
@test.attr(type=['gate', 'negative'])
def test_post_object_using_form_expired(self):
@@ -117,11 +118,12 @@
url = "%s/%s" % (self.container_name, self.object_name)
exc = self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.object_client.post,
url, body, headers=headers)
self.assertIn('FormPost: Form Expired', str(exc))
+ @test.idempotent_id('b277257f-113c-4499-b8d1-5fead79f7360')
@test.requires_ext(extension='formpost', service='object')
@test.attr(type='gate')
def test_post_object_using_form_invalid_signature(self):
@@ -133,7 +135,7 @@
url = "%s/%s" % (self.container_name, self.object_name)
exc = self.assertRaises(
- exceptions.Unauthorized,
+ lib_exc.Unauthorized,
self.object_client.post,
url, body, headers=headers)
self.assertIn('FormPost: Invalid Signature', str(exc))
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index cbca5e8..a4d0377 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -85,6 +85,7 @@
self.assertNotIn('x-object-meta-' + meta_key, resp)
@test.attr(type='gate')
+ @test.idempotent_id('5b4ce26f-3545-46c9-a2ba-5754358a4c62')
def test_create_object(self):
# create object
object_name = data_utils.rand_name(name='TestObject')
@@ -104,6 +105,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('5daebb1d-f0d5-4dc9-b541-69672eff00b0')
def test_create_object_with_content_disposition(self):
# create object with content_disposition
object_name = data_utils.rand_name(name='TestObject')
@@ -126,6 +128,7 @@
self.assertEqual(body, data)
@test.attr(type='gate')
+ @test.idempotent_id('605f8317-f945-4bee-ae91-013f1da8f0a0')
def test_create_object_with_content_encoding(self):
# create object with content_encoding
object_name = data_utils.rand_name(name='TestObject')
@@ -153,6 +156,7 @@
self.assertEqual(body, data_before)
@test.attr(type='gate')
+ @test.idempotent_id('73820093-0503-40b1-a478-edf0e69c7d1f')
def test_create_object_with_etag(self):
# create object with etag
object_name = data_utils.rand_name(name='TestObject')
@@ -172,6 +176,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('84dafe57-9666-4f6d-84c8-0814d37923b8')
def test_create_object_with_expect_continue(self):
# create object with expect_continue
object_name = data_utils.rand_name(name='TestObject')
@@ -198,6 +203,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('4f84422a-e2f2-4403-b601-726a4220b54e')
def test_create_object_with_transfer_encoding(self):
# create object with transfer_encoding
object_name = data_utils.rand_name(name='TestObject')
@@ -215,6 +221,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('0f3d62a6-47e3-4554-b0e5-1a5dc372d501')
def test_create_object_with_x_fresh_metadata(self):
# create object with x_fresh_metadata
object_name_base = data_utils.rand_name(name='TestObject')
@@ -241,6 +248,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('1c7ed3e4-2099-406b-b843-5301d4811baf')
def test_create_object_with_x_object_meta(self):
# create object with object_meta
object_name = data_utils.rand_name(name='TestObject')
@@ -260,6 +268,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('e4183917-33db-4153-85cc-4dacbb938865')
def test_create_object_with_x_object_metakey(self):
# create object with the blank value of metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -279,6 +288,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('ce798afc-b278-45de-a5ce-2ea124b98b99')
def test_create_object_with_x_remove_object_meta(self):
# create object with x_remove_object_meta
object_name = data_utils.rand_name(name='TestObject')
@@ -302,6 +312,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('ad21e342-7916-4f9e-ab62-a1f885f2aaf9')
def test_create_object_with_x_remove_object_metakey(self):
# create object with the blank value of remove metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -325,6 +336,7 @@
self.assertEqual(data, body)
@test.attr(type='gate')
+ @test.idempotent_id('17738d45-03bd-4d45-9e0b-7b2f58f98687')
def test_delete_object(self):
# create object
object_name = data_utils.rand_name(name='TestObject')
@@ -337,6 +349,7 @@
self.assertHeaders(resp, 'Object', 'DELETE')
@test.attr(type='smoke')
+ @test.idempotent_id('7a94c25d-66e6-434c-9c38-97d4e2c29945')
def test_update_object_metadata(self):
# update object metadata
object_name, data = self._create_object()
@@ -355,6 +368,7 @@
self.assertIn('x-object-meta-test-meta', resp)
self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
+ @test.idempotent_id('48650ed0-c189-4e1e-ad6b-1d4770c6e134')
def test_update_object_metadata_with_remove_metadata(self):
# update object metadata with remove metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -379,6 +393,7 @@
self.assertNotIn('x-object-meta-test-meta1', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('f726174b-2ded-4708-bff7-729d12ce1f84')
def test_update_object_metadata_with_create_and_remove_metadata(self):
# creation and deletion of metadata with one request
object_name = data_utils.rand_name(name='TestObject')
@@ -406,6 +421,7 @@
self.assertEqual(resp['x-object-meta-test-meta2'], 'Meta2')
@test.attr(type='smoke')
+ @test.idempotent_id('08854588-6449-4bb7-8cca-f2e1040f5e6f')
def test_update_object_metadata_with_x_object_manifest(self):
# update object metadata with x_object_manifest
@@ -432,6 +448,7 @@
self.assertIn('x-object-manifest', resp)
self.assertNotEqual(len(resp['x-object-manifest']), 0)
+ @test.idempotent_id('0dbbe89c-6811-4d84-a2df-eca2bdd40c0e')
def test_update_object_metadata_with_x_object_metakey(self):
# update object metadata with a blenk value of metadata
object_name, data = self._create_object()
@@ -451,6 +468,7 @@
self.assertEqual(resp['x-object-meta-test-meta'], '')
@test.attr(type='smoke')
+ @test.idempotent_id('9a88dca4-b684-425b-806f-306cd0e57e42')
def test_update_object_metadata_with_x_remove_object_metakey(self):
# update object metadata with a blank value of remove metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -475,6 +493,7 @@
self.assertNotIn('x-object-meta-test-meta', resp)
@test.attr(type='smoke')
+ @test.idempotent_id('9a447cf6-de06-48de-8226-a8c6ed31caf2')
def test_list_object_metadata(self):
# get object metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -493,6 +512,7 @@
self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
@test.attr(type='smoke')
+ @test.idempotent_id('170fb90e-f5c3-4b1f-ae1b-a18810821172')
def test_list_no_object_metadata(self):
# get empty list of object metadata
object_name, data = self._create_object()
@@ -504,6 +524,7 @@
self.assertNotIn('x-object-meta-', str(resp))
@test.attr(type='smoke')
+ @test.idempotent_id('23a3674c-d6de-46c3-86af-ff92bfc8a3da')
def test_list_object_metadata_with_x_object_manifest(self):
# get object metadata with x_object_manifest
@@ -544,6 +565,7 @@
'%s/%s' % (self.container_name, object_name))
@test.attr(type='smoke')
+ @test.idempotent_id('02610ba7-86b7-4272-9ed8-aa8d417cb3cd')
def test_get_object(self):
# retrieve object's data (in response body)
@@ -557,6 +579,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('005f9bf6-e06d-41ec-968e-96c78e0b1d82')
def test_get_object_with_metadata(self):
# get object with metadata
object_name = data_utils.rand_name(name='TestObject')
@@ -576,6 +599,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('05a1890e-7db9-4a6c-90a8-ce998a2bddfa')
def test_get_object_with_range(self):
# get object with range
object_name = data_utils.rand_name(name='TestObject')
@@ -594,6 +618,7 @@
self.assertEqual(body, data[rand_num - 3: rand_num])
@test.attr(type='smoke')
+ @test.idempotent_id('11b4515b-7ba7-4ca8-8838-357ded86fc10')
def test_get_object_with_x_object_manifest(self):
# get object with x_object_manifest
@@ -637,6 +662,7 @@
self.assertEqual(''.join(data_segments), body)
@test.attr(type='smoke')
+ @test.idempotent_id('c05b4013-e4de-47af-be84-e598062b16fc')
def test_get_object_with_if_match(self):
# get object with if_match
object_name = data_utils.rand_name(name='TestObject')
@@ -657,6 +683,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('be133639-e5d2-4313-9b1f-2d59fc054a16')
def test_get_object_with_if_modified_since(self):
# get object with if_modified_since
object_name = data_utils.rand_name(name='TestObject')
@@ -676,6 +703,7 @@
self.assertHeaders(resp, 'Object', 'GET')
self.assertEqual(body, data)
+ @test.idempotent_id('641500d5-1612-4042-a04d-01fc4528bc30')
def test_get_object_with_if_none_match(self):
# get object with if_none_match
object_name = data_utils.rand_name(name='TestObject')
@@ -698,6 +726,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('0aa1201c-10aa-467a-bee7-63cbdd463152')
def test_get_object_with_if_unmodified_since(self):
# get object with if_unmodified_since
object_name, data = self._create_object()
@@ -713,6 +742,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('94587078-475f-48f9-a40f-389c246e31cd')
def test_get_object_with_x_newest(self):
# get object with x_newest
object_name, data = self._create_object()
@@ -726,6 +756,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('1a9ab572-1b66-4981-8c21-416e2a5e6011')
def test_copy_object_in_same_container(self):
# create source object
src_object_name = data_utils.rand_name(name='SrcObject')
@@ -752,6 +783,7 @@
self.assertEqual(body, src_data)
@test.attr(type='smoke')
+ @test.idempotent_id('2248abba-415d-410b-9c30-22dff9cd6e67')
def test_copy_object_to_itself(self):
# change the content type of an existing object
@@ -773,6 +805,7 @@
self.assertEqual(resp['content-type'], metadata['content-type'])
@test.attr(type='smoke')
+ @test.idempotent_id('06f90388-2d0e-40aa-934c-e9a8833e958a')
def test_copy_object_2d_way(self):
# create source object
src_object_name = data_utils.rand_name(name='SrcObject')
@@ -799,6 +832,7 @@
self._check_copied_obj(dst_object_name, src_data)
@test.attr(type='smoke')
+ @test.idempotent_id('aa467252-44f3-472a-b5ae-5b57c3c9c147')
def test_copy_object_across_containers(self):
# create a container to use as asource container
src_container_name = data_utils.rand_name(name='TestSourceContainer')
@@ -839,6 +873,7 @@
self.assertEqual(resp[actual_meta_key], meta_value)
@test.attr(type='smoke')
+ @test.idempotent_id('5a9e2cc6-85b6-46fc-916d-0cbb7a88e5fd')
def test_copy_object_with_x_fresh_metadata(self):
# create source object
metadata = {'x-object-meta-src': 'src_value'}
@@ -859,6 +894,7 @@
self._check_copied_obj(dst_object_name, data, not_in_meta=["src"])
@test.attr(type='smoke')
+ @test.idempotent_id('a28a8b99-e701-4d7e-9d84-3b66f121460b')
def test_copy_object_with_x_object_metakey(self):
# create source object
metadata = {'x-object-meta-src': 'src_value'}
@@ -881,6 +917,7 @@
self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
@test.attr(type='smoke')
+ @test.idempotent_id('edabedca-24c3-4322-9b70-d6d9f942a074')
def test_copy_object_with_x_object_meta(self):
# create source object
metadata = {'x-object-meta-src': 'src_value'}
@@ -903,6 +940,7 @@
self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
@test.attr(type='gate')
+ @test.idempotent_id('e3e6a64a-9f50-4955-b987-6ce6767c97fb')
def test_object_upload_in_segments(self):
# create object
object_name = data_utils.rand_name(name='LObject')
@@ -945,6 +983,7 @@
self.assertEqual(''.join(data_segments), body)
@test.attr(type='gate')
+ @test.idempotent_id('50d01f12-526f-4360-9ac2-75dd508d7b68')
def test_get_object_if_different(self):
# http://en.wikipedia.org/wiki/HTTP_ETag
# Make a conditional request for an object using the If-None-Match
@@ -987,6 +1026,7 @@
super(PublicObjectTest, self).tearDown()
@test.attr(type='smoke')
+ @test.idempotent_id('07c9cf95-c0d4-4b49-b9c8-0ef2c9b27193')
def test_access_public_container_object_without_using_creds(self):
# make container public-readable and access an object in it object
# anonymously, without using credentials
@@ -1025,6 +1065,7 @@
self.assertEqual(body, data)
@test.attr(type='smoke')
+ @test.idempotent_id('54e2a2fe-42dc-491b-8270-8e4217dd4cdc')
def test_access_public_object_with_another_user_creds(self):
# make container public-readable and access an object in it using
# another user's credentials
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 6622349..b013752 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -15,10 +15,11 @@
import hashlib
import json
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest.common import custom_matchers
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
# Each segment, except for the final one, must be at least 1 megabyte
@@ -39,7 +40,7 @@
self.object_client.delete_object(
self.container_name,
obj)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
self.container_client.delete_container(self.container_name)
super(ObjectSloTest, self).tearDown()
@@ -109,6 +110,7 @@
self.assertHeaders(resp, 'Object', method)
@test.attr(type='gate')
+ @test.idempotent_id('2c3f24a6-36e8-4711-9aa2-800ee1fc7b5b')
def test_upload_manifest(self):
# create static large object from multipart manifest
manifest = self._create_manifest()
@@ -123,6 +125,7 @@
self._assertHeadersSLO(resp, 'PUT')
@test.attr(type='gate')
+ @test.idempotent_id('e69ad766-e1aa-44a2-bdd2-bf62c09c1456')
def test_list_large_object_metadata(self):
# list static large object metadata using multipart manifest
object_name = self._create_large_object()
@@ -134,6 +137,7 @@
self._assertHeadersSLO(resp, 'HEAD')
@test.attr(type='gate')
+ @test.idempotent_id('49bc49bc-dd1b-4c0f-904e-d9f10b830ee8')
def test_retrieve_large_object(self):
# list static large object using multipart manifest
object_name = self._create_large_object()
@@ -148,6 +152,7 @@
self.assertEqual(body, sum_data)
@test.attr(type='gate')
+ @test.idempotent_id('87b6dfa1-abe9-404d-8bf0-6c3751e6aa77')
def test_delete_large_object(self):
# delete static large object using multipart manifest
object_name = self._create_large_object()
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index dd4fd17..e6b0b05 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -94,6 +92,7 @@
return url
@test.attr(type='gate')
+ @test.idempotent_id('f91c96d4-1230-4bba-8eb9-84476d18d991')
@test.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url(self):
expires = self._get_expiry_date()
@@ -113,6 +112,7 @@
self.assertHeaders(resp, 'Object', 'HEAD')
@test.attr(type='gate')
+ @test.idempotent_id('671f9583-86bd-4128-a034-be282a68c5d8')
@test.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url_key_2(self):
key2 = 'Meta2-'
@@ -137,6 +137,7 @@
self.assertEqual(body, self.content)
@test.attr(type='gate')
+ @test.idempotent_id('9b08dade-3571-4152-8a4f-a4f2a873a735')
@test.requires_ext(extension='tempurl', service='object')
def test_put_object_using_temp_url(self):
new_data = data_utils.arbitrary_string(
@@ -165,6 +166,7 @@
self.assertEqual(body, new_data)
@test.attr(type='gate')
+ @test.idempotent_id('249a0111-5ad3-4534-86a7-1993d55f9185')
@test.requires_ext(extension='tempurl', service='object')
def test_head_object_using_temp_url(self):
expires = self._get_expiry_date()
@@ -179,6 +181,7 @@
self.assertHeaders(resp, 'Object', 'HEAD')
@test.attr(type='gate')
+ @test.idempotent_id('9d9cfd90-708b-465d-802c-e4a8090b823d')
@test.requires_ext(extension='tempurl', service='object')
def test_get_object_using_temp_url_with_inline_query_parameter(self):
expires = self._get_expiry_date()
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index b752348..343749e 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -1,7 +1,5 @@
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Joe H. Rahme <joe.hakim.rahme@enovance.com>
-#
# 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
@@ -19,9 +17,10 @@
import time
import urlparse
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.object_storage import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
@@ -92,6 +91,7 @@
return url
@test.attr(type=['gate', 'negative'])
+ @test.idempotent_id('5a583aca-c804-41ba-9d9a-e7be132bdf0b')
@test.requires_ext(extension='tempurl', service='object')
def test_get_object_after_expiration_time(self):
@@ -104,5 +104,5 @@
# temp URL is valid for 1 seconds, let's wait 2
time.sleep(2)
- self.assertRaises(exceptions.Unauthorized,
+ self.assertRaises(lib_exc.Unauthorized,
self.object_client.get, url)
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index da40e5a..225159f 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -45,6 +45,7 @@
self.assertEqual(header_value, versioned)
@test.attr(type='smoke')
+ @test.idempotent_id('a151e158-dcbf-4a1f-a1e7-46cd65895a6f')
@testtools.skipIf(
not CONF.object_storage_feature_enabled.object_versioning,
'Object-versioning is disabled')
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 97777db..b8b0562 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -12,12 +12,12 @@
import os.path
+from tempest_lib import exceptions as lib_exc
import yaml
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
import tempest.test
@@ -30,14 +30,19 @@
"""Base test case class for all Orchestration API tests."""
@classmethod
- def resource_setup(cls):
- super(BaseOrchestrationTest, cls).resource_setup()
- cls.os = clients.Manager()
+ def skip_checks(cls):
+ super(BaseOrchestrationTest, cls).skip_checks()
if not CONF.service_available.heat:
raise cls.skipException("Heat support is required")
- cls.build_timeout = CONF.orchestration.build_timeout
- cls.build_interval = CONF.orchestration.build_interval
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseOrchestrationTest, cls).setup_credentials()
+ cls.os = clients.Manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseOrchestrationTest, cls).setup_clients()
cls.orchestration_client = cls.os.orchestration_client
cls.client = cls.orchestration_client
cls.servers_client = cls.os.servers_client
@@ -45,6 +50,12 @@
cls.network_client = cls.os.network_client
cls.volumes_client = cls.os.volumes_client
cls.images_v2_client = cls.os.image_client_v2
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseOrchestrationTest, cls).resource_setup()
+ cls.build_timeout = CONF.orchestration.build_timeout
+ cls.build_interval = CONF.orchestration.build_interval
cls.stacks = []
cls.keypairs = []
cls.images = []
@@ -59,7 +70,7 @@
@classmethod
def _get_identity_admin_client(cls):
"""Returns an instance of the Identity Admin API client."""
- manager = clients.AdminManager(interface=cls._interface)
+ manager = clients.AdminManager()
admin_client = manager.identity_client
return admin_client
@@ -84,14 +95,14 @@
for stack_identifier in cls.stacks:
try:
cls.client.delete_stack(stack_identifier)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
for stack_identifier in cls.stacks:
try:
cls.client.wait_for_stack_status(
stack_identifier, 'DELETE_COMPLETE')
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@classmethod
@@ -125,7 +136,7 @@
for image_id in cls.images:
try:
cls.images_v2_client.delete_image(image_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@classmethod
diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py
index 96e1c50..2989709 100644
--- a/tempest/api/orchestration/stacks/test_environment.py
+++ b/tempest/api/orchestration/stacks/test_environment.py
@@ -25,6 +25,7 @@
class StackEnvironmentTest(base.BaseOrchestrationTest):
@test.attr(type='gate')
+ @test.idempotent_id('37d4346b-1abd-4442-b7b1-2a4e5749a1e3')
def test_environment_parameter(self):
"""Test passing a stack parameter via the environment."""
stack_name = data_utils.rand_name('heat')
@@ -42,6 +43,7 @@
self.assertEqual(20, len(random_value))
@test.attr(type='gate')
+ @test.idempotent_id('73bce717-ad22-4853-bbef-6ed89b632701')
def test_environment_provider_resource(self):
"""Test passing resource_registry defining a provider resource."""
stack_name = data_utils.rand_name('heat')
@@ -71,6 +73,7 @@
self.assertEqual(expected_length, len(random_value))
@test.attr(type='gate')
+ @test.idempotent_id('9d682e5a-f4bb-47d5-8472-9d3cacb855df')
def test_files_provider_resource(self):
"""Test untyped defining of a provider resource via "files"."""
# It's also possible to specify the filename directly in the template.
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index 8ee62ab..833fb28 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -11,11 +11,11 @@
# under the License.
import logging
+from tempest_lib import exceptions as lib_exc
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -26,6 +26,7 @@
class TestServerStackLimits(base.BaseOrchestrationTest):
@test.attr(type='gate')
+ @test.idempotent_id('ec9bed71-c460-45c9-ab98-295caa9fd76b')
def test_exceed_max_template_size_fails(self):
stack_name = data_utils.rand_name('heat')
fill = 'A' * CONF.orchestration.max_template_size
@@ -34,11 +35,12 @@
Description: '%s'
Outputs:
Foo: bar''' % fill
- ex = self.assertRaises(exceptions.BadRequest, self.create_stack,
+ ex = self.assertRaises(lib_exc.BadRequest, self.create_stack,
stack_name, template)
self.assertIn('Template exceeds maximum allowed size', str(ex))
@test.attr(type='gate')
+ @test.idempotent_id('d1b83e73-7cad-4a22-9839-036548c5387c')
def test_exceed_max_resources_per_stack(self):
stack_name = data_utils.rand_name('heat')
# Create a big template, one resource more than the limit
@@ -48,6 +50,6 @@
for i in range(num_resources):
template += rsrc_snippet % i
- ex = self.assertRaises(exceptions.BadRequest, self.create_stack,
+ ex = self.assertRaises(lib_exc.BadRequest, self.create_stack,
stack_name, template)
self.assertIn('Maximum resources per stack exceeded', str(ex))
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index ea6d4be..253d197 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -30,15 +30,27 @@
class NeutronResourcesTestJSON(base.BaseOrchestrationTest):
@classmethod
- def resource_setup(cls):
- super(NeutronResourcesTestJSON, cls).resource_setup()
+ def skip_checks(cls):
+ super(NeutronResourcesTestJSON, cls).skip_checks()
if not CONF.orchestration.image_ref:
raise cls.skipException("No image available to test")
- os = clients.Manager()
if not CONF.service_available.neutron:
raise cls.skipException("Neutron support is required")
+
+ @classmethod
+ def setup_credentials(cls):
+ super(NeutronResourcesTestJSON, cls).setup_credentials()
+ cls.os = clients.Manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(NeutronResourcesTestJSON, cls).setup_clients()
+ cls.network_client = cls.os.network_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(NeutronResourcesTestJSON, cls).resource_setup()
cls.neutron_basic_template = cls.load_template('neutron_basic')
- cls.network_client = os.network_client
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('neutron_basic')
cls.keypair_name = (CONF.orchestration.keypair_name or
@@ -75,8 +87,8 @@
'Server')
server_id = body['physical_resource_id']
LOG.debug('Console output for %s', server_id)
- _, output = cls.servers_client.get_console_output(
- server_id, None)
+ output = cls.servers_client.get_console_output(
+ server_id, None).data
LOG.debug(output)
raise e
@@ -85,6 +97,7 @@
cls.test_resources[resource['logical_resource_id']] = resource
@test.attr(type='slow')
+ @test.idempotent_id('f9e2664c-bc44-4eef-98b6-495e4f9d74b3')
def test_created_resources(self):
"""Verifies created neutron resources."""
resources = [('Network', self.neutron_basic_template['resources'][
@@ -103,6 +116,7 @@
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
@test.attr(type='slow')
+ @test.idempotent_id('c572b915-edb1-4e90-b196-c7199a6848c0')
@test.services('network')
def test_created_network(self):
"""Verifies created network."""
@@ -115,6 +129,7 @@
'Network']['properties']['name'], network['name'])
@test.attr(type='slow')
+ @test.idempotent_id('e8f84b96-f9d7-4684-ad5f-340203e9f2c2')
@test.services('network')
def test_created_subnet(self):
"""Verifies created subnet."""
@@ -133,6 +148,7 @@
self.assertEqual(str(self.subnet_cidr), subnet['cidr'])
@test.attr(type='slow')
+ @test.idempotent_id('96af4c7f-5069-44bc-bdcf-c0390f8a67d1')
@test.services('network')
def test_created_router(self):
"""Verifies created router."""
@@ -146,6 +162,7 @@
self.assertEqual(True, router['admin_state_up'])
@test.attr(type='slow')
+ @test.idempotent_id('89f605bd-153e-43ee-a0ed-9919b63423c5')
@test.services('network')
def test_created_router_interface(self):
"""Verifies created router interface."""
@@ -169,11 +186,12 @@
router_interface_ip)
@test.attr(type='slow')
+ @test.idempotent_id('75d85316-4ac2-4c0e-a1a9-edd2148fc10e')
@test.services('compute', 'network')
def test_created_server(self):
"""Verifies created sever."""
server_id = self.test_resources.get('Server')['physical_resource_id']
- _, server = self.servers_client.get_server(server_id)
+ server = self.servers_client.get_server(server_id)
self.assertEqual(self.keypair_name, server['key_name'])
self.assertEqual('ACTIVE', server['status'])
network = server['addresses'][self.neutron_basic_template['resources'][
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index db1ac9a..e8f3522 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -54,6 +54,7 @@
return stacks
@test.attr(type='gate')
+ @test.idempotent_id('065c652a-720d-4760-9132-06aedeb8e3ab')
def test_stack_list(self):
"""Created stack should be in the list of existing stacks."""
stacks = self._list_stacks()
@@ -61,6 +62,7 @@
self.assertIn(self.stack_name, stacks_names)
@test.attr(type='gate')
+ @test.idempotent_id('992f96e3-41ee-4ff6-91c7-bcfb670c0919')
def test_stack_show(self):
"""Getting details about created stack should be possible."""
stack = self.client.get_stack(self.stack_name)
@@ -80,6 +82,7 @@
self.assertEqual('fluffy', stack['outputs'][0]['output_key'])
@test.attr(type='gate')
+ @test.idempotent_id('fe719f7a-305a-44d8-bbb5-c91e93d9da17')
def test_suspend_resume_stack(self):
"""Suspend and resume a stack."""
self.client.suspend_stack(self.stack_identifier)
@@ -90,6 +93,7 @@
'RESUME_COMPLETE')
@test.attr(type='gate')
+ @test.idempotent_id('c951d55e-7cce-4c1f-83a0-bad735437fa6')
def test_list_resources(self):
"""Getting list of created resources for the stack should be possible.
"""
@@ -97,6 +101,7 @@
self.assertEqual({self.resource_name: self.resource_type}, resources)
@test.attr(type='gate')
+ @test.idempotent_id('2aba03b3-392f-4237-900b-1f5a5e9bd962')
def test_show_resource(self):
"""Getting details about created resource should be possible."""
resource = self.client.get_resource(self.stack_identifier,
@@ -111,6 +116,7 @@
self.assertEqual(self.resource_type, resource['resource_type'])
@test.attr(type='gate')
+ @test.idempotent_id('898070a9-eba5-4fae-b7d6-cf3ffa03090f')
def test_resource_metadata(self):
"""Getting metadata for created resources should be possible."""
metadata = self.client.show_resource_metadata(
@@ -120,6 +126,7 @@
self.assertEqual(['Tom', 'Stinky'], metadata.get('kittens', None))
@test.attr(type='gate')
+ @test.idempotent_id('46567533-0a7f-483b-8942-fa19e0f17839')
def test_list_events(self):
"""Getting list of created events for the stack should be possible."""
events = self.client.list_events(self.stack_identifier)
@@ -135,6 +142,7 @@
self.assertIn('CREATE_COMPLETE', resource_statuses)
@test.attr(type='gate')
+ @test.idempotent_id('92465723-1673-400a-909d-4773757a3f21')
def test_show_event(self):
"""Getting details about an event should be possible."""
events = self.client.list_resource_events(self.stack_identifier,
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 772bab3..6d2dcc7 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -49,6 +49,7 @@
cls.test_resources[resource['logical_resource_id']] = resource
@test.attr(type='gate')
+ @test.idempotent_id('b476eac2-a302-4815-961f-18c410a2a537')
def test_created_resources(self):
"""Verifies created keypair resource."""
@@ -69,6 +70,7 @@
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
@test.attr(type='gate')
+ @test.idempotent_id('8d77dec7-91fd-45a6-943d-5abd45e338a4')
def test_stack_keypairs_output(self):
stack = self.client.get_stack(self.stack_name)
self.assertIsInstance(stack, dict)
diff --git a/tempest/api/orchestration/stacks/test_resource_types.py b/tempest/api/orchestration/stacks/test_resource_types.py
index e204894..32b0b8e 100644
--- a/tempest/api/orchestration/stacks/test_resource_types.py
+++ b/tempest/api/orchestration/stacks/test_resource_types.py
@@ -17,6 +17,7 @@
class ResourceTypesTest(base.BaseOrchestrationTest):
@test.attr(type='smoke')
+ @test.idempotent_id('7123d082-3577-4a30-8f00-f805327c4ffd')
def test_resource_type_list(self):
"""Verify it is possible to list resource types."""
resource_types = self.client.list_resource_types()
@@ -24,6 +25,7 @@
self.assertIn('OS::Nova::Server', resource_types)
@test.attr(type='smoke')
+ @test.idempotent_id('0e85a483-828b-4a28-a0e3-f0a21809192b')
def test_resource_type_show(self):
"""Verify it is possible to get schema about resource types."""
resource_types = self.client.list_resource_types()
@@ -36,9 +38,12 @@
self.assertEqual(resource_type, type_schema['resource_type'])
@test.attr(type='smoke')
+ @test.idempotent_id('8401821d-65fe-4d43-9fa3-57d5ce3a35c7')
def test_resource_type_template(self):
"""Verify it is possible to get template about resource types."""
type_template = self.client.get_resource_type_template(
'OS::Nova::Server')
- self.assert_fields_in_dict(type_template, 'Outputs',
- 'Parameters', 'Resources')
\ No newline at end of file
+ self.assert_fields_in_dict(
+ type_template,
+ 'Outputs',
+ 'Parameters', 'Resources')
diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index 8903d4c..7387c62 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.py
@@ -10,10 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest import test
@@ -70,16 +71,17 @@
self.client.delete_software_deploy(deploy_id)
# Testing that it is really gone
self.assertRaises(
- exceptions.NotFound, self.client.get_software_deploy,
+ lib_exc.NotFound, self.client.get_software_deploy,
self.deployment_id)
def _config_delete(self, config_id):
self.client.delete_software_config(config_id)
# Testing that it is really gone
self.assertRaises(
- exceptions.NotFound, self.client.get_software_config, config_id)
+ lib_exc.NotFound, self.client.get_software_config, config_id)
@test.attr(type='smoke')
+ @test.idempotent_id('136162ed-9445-4b9c-b7fc-306af8b5da99')
def test_get_software_config(self):
"""Testing software config get."""
for conf in self.configs:
@@ -87,6 +89,7 @@
self._validate_config(conf, api_config)
@test.attr(type='smoke')
+ @test.idempotent_id('1275c835-c967-4a2c-8d5d-ad533447ed91')
def test_get_deployment_list(self):
"""Getting a list of all deployments"""
deploy_list = self.client.get_software_deploy_list()
@@ -95,6 +98,7 @@
self.assertIn(self.deployment_id, deploy_ids)
@test.attr(type='smoke')
+ @test.idempotent_id('fe7cd9f9-54b1-429c-a3b7-7df8451db913')
def test_get_deployment_metadata(self):
"""Testing deployment metadata get"""
metadata = self.client.get_software_deploy_meta(self.server_id)
@@ -111,6 +115,7 @@
deployment['software_deployment']['config_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('f29d21f3-ed75-47cf-8cdc-ef1bdeb4c674')
def test_software_deployment_create_validate(self):
"""Testing software deployment was created as expected."""
# Asserting that all fields were created
@@ -123,6 +128,7 @@
self.status_reason, self.configs[0]['id'])
@test.attr(type='smoke')
+ @test.idempotent_id('2ac43ab3-34f2-415d-be2e-eabb4d14ee32')
def test_software_deployment_update_no_metadata_change(self):
"""Testing software deployment update without metadata change."""
metadata = self.client.get_software_deploy_meta(self.server_id)
@@ -146,6 +152,7 @@
test_metadata['metadata'][0][key])
@test.attr(type='smoke')
+ @test.idempotent_id('92c48944-d79d-4595-a840-8e1a581c1a72')
def test_software_deployment_update_with_metadata_change(self):
"""Testing software deployment update with metadata change."""
metadata = self.client.get_software_deploy_meta(self.server_id)
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 5cdd8b4..a9b3a6b 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -27,11 +27,13 @@
super(StacksTestJSON, cls).resource_setup()
@test.attr(type='smoke')
+ @test.idempotent_id('d35d628c-07f6-4674-85a1-74db9919e986')
def test_stack_list_responds(self):
stacks = self.client.list_stacks()
self.assertIsInstance(stacks, list)
@test.attr(type='smoke')
+ @test.idempotent_id('10498bd5-a83e-4b62-a817-ce24afe938fe')
def test_stack_crud_no_resources(self):
stack_name = data_utils.rand_name('heat')
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index 0288fd4..1290dfe 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
-# Author: Chmouel Boudjnah <chmouel@enovance.com>
-#
# 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
@@ -26,15 +24,27 @@
class SwiftResourcesTestJSON(base.BaseOrchestrationTest):
@classmethod
+ def skip_checks(cls):
+ super(SwiftResourcesTestJSON, cls).skip_checks()
+ if not CONF.service_available.swift:
+ raise cls.skipException("Swift support is required")
+
+ @classmethod
+ def setup_credentials(cls):
+ super(SwiftResourcesTestJSON, cls).setup_credentials()
+ cls.os = clients.Manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(SwiftResourcesTestJSON, cls).setup_clients()
+ cls.account_client = cls.os.account_client
+ cls.container_client = cls.os.container_client
+
+ @classmethod
def resource_setup(cls):
super(SwiftResourcesTestJSON, cls).resource_setup()
cls.stack_name = data_utils.rand_name('heat')
template = cls.read_template('swift_basic')
- os = clients.Manager()
- if not CONF.service_available.swift:
- raise cls.skipException("Swift support is required")
- cls.account_client = os.account_client
- cls.container_client = os.container_client
# create the stack
cls.stack_identifier = cls.create_stack(
cls.stack_name,
@@ -46,6 +56,7 @@
for resource in resources:
cls.test_resources[resource['logical_resource_id']] = resource
+ @test.idempotent_id('1a6fe69e-4be4-4990-9a7a-84b6f18019cb')
def test_created_resources(self):
"""Created stack should be in the list of existing stacks."""
swift_basic_template = self.load_template('swift_basic')
@@ -60,6 +71,7 @@
self.assertEqual(resource_name, resource['logical_resource_id'])
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
+ @test.idempotent_id('bd438b18-5494-4d5a-9ce6-d2a942ec5060')
@test.services('object_storage')
def test_created_containers(self):
params = {'format': 'json'}
@@ -69,6 +81,7 @@
if cont['name'].startswith(self.stack_name)]
self.assertEqual(2, len(created_containers))
+ @test.idempotent_id('73d0c093-9922-44a0-8b1d-1fc092dee367')
@test.services('object_storage')
def test_acl(self):
acl_headers = ('x-container-meta-web-index', 'x-container-read')
@@ -86,6 +99,7 @@
for h in acl_headers:
self.assertIn(h, headers)
+ @test.idempotent_id('fda06135-6777-4594-aefa-0f6107169698')
@test.services('object_storage')
def test_metadata(self):
swift_basic_template = self.load_template('swift_basic')
diff --git a/tempest/api/orchestration/stacks/test_templates.py b/tempest/api/orchestration/stacks/test_templates.py
index 6113cab..d0fc1cf 100644
--- a/tempest/api/orchestration/stacks/test_templates.py
+++ b/tempest/api/orchestration/stacks/test_templates.py
@@ -36,11 +36,13 @@
cls.parameters = {}
@test.attr(type='gate')
+ @test.idempotent_id('47430699-c368-495e-a1db-64c26fd967d7')
def test_show_template(self):
"""Getting template used to create the stack."""
self.client.show_template(self.stack_identifier)
@test.attr(type='gate')
+ @test.idempotent_id('ed53debe-8727-46c5-ab58-eba6090ec4de')
def test_validate_template(self):
"""Validating template passing it content."""
self.client.validate_template(self.template,
diff --git a/tempest/api/orchestration/stacks/test_templates_negative.py b/tempest/api/orchestration/stacks/test_templates_negative.py
index 9082107..ebba694 100644
--- a/tempest/api/orchestration/stacks/test_templates_negative.py
+++ b/tempest/api/orchestration/stacks/test_templates_negative.py
@@ -12,8 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.orchestration import base
-from tempest import exceptions
from tempest import test
@@ -35,9 +36,10 @@
cls.parameters = {}
@test.attr(type=['gate', 'negative'])
+ @test.idempotent_id('5586cbca-ddc4-4152-9db8-fa1ce5fc1876')
def test_validate_template_url(self):
"""Validating template passing url to it."""
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.validate_template_url,
template_url=self.invalid_template_url,
parameters=self.parameters)
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 6fddb21..5a1a6d7 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -12,10 +12,11 @@
import logging
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
@@ -26,8 +27,8 @@
class CinderResourcesTest(base.BaseOrchestrationTest):
@classmethod
- def resource_setup(cls):
- super(CinderResourcesTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(CinderResourcesTest, cls).skip_checks()
if not CONF.service_available.cinder:
raise cls.skipException('Cinder support is required')
@@ -54,6 +55,7 @@
'name'], self.get_stack_output(stack_identifier, 'display_name'))
@test.attr(type='gate')
+ @test.idempotent_id('c3243329-7bdd-4730-b402-4d19d50c41d8')
@test.services('volume')
def test_cinder_volume_create_delete(self):
"""Create and delete a volume via OS::Cinder::Volume."""
@@ -73,7 +75,7 @@
# Delete the stack and ensure the volume is gone
self.client.delete_stack(stack_identifier)
self.client.wait_for_stack_status(stack_identifier, 'DELETE_COMPLETE')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.volumes_client.get_volume,
volume_id)
@@ -83,6 +85,7 @@
self.volumes_client.wait_for_resource_deletion(volume_id)
@test.attr(type='gate')
+ @test.idempotent_id('ea8b3a46-b932-4c18-907a-fe23f00b33f8')
@test.services('volume')
def test_cinder_volume_create_delete_retain(self):
"""Ensure the 'Retain' deletion policy is respected."""
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 8885187..c521b37 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -12,6 +12,8 @@
import time
+from tempest_lib import exceptions as lib_exc
+
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -26,18 +28,29 @@
"""Base test case class for all Telemetry API tests."""
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(BaseTelemetryTest, cls).skip_checks()
if not CONF.service_available.ceilometer:
raise cls.skipException("Ceilometer support is required")
- cls.set_network_resources()
- super(BaseTelemetryTest, cls).resource_setup()
- os = cls.get_client_manager()
- cls.telemetry_client = os.telemetry_client
- cls.servers_client = os.servers_client
- cls.flavors_client = os.flavors_client
- cls.image_client = os.image_client
- cls.image_client_v2 = os.image_client_v2
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources()
+ super(BaseTelemetryTest, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseTelemetryTest, cls).setup_clients()
+ cls.telemetry_client = cls.os.telemetry_client
+ cls.servers_client = cls.os.servers_client
+ cls.flavors_client = cls.os.flavors_client
+ cls.image_client = cls.os.image_client
+ cls.image_client_v2 = cls.os.image_client_v2
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseTelemetryTest, cls).resource_setup()
cls.nova_notifications = ['memory', 'vcpus', 'disk.root.size',
'disk.ephemeral.size']
@@ -60,12 +73,12 @@
@classmethod
def create_server(cls):
- resp, body = cls.servers_client.create_server(
+ body = cls.servers_client.create_server(
data_utils.rand_name('ceilometer-instance'),
CONF.compute.image_ref, CONF.compute.flavor_ref,
wait_until='ACTIVE')
cls.server_ids.append(body['id'])
- return resp, body
+ return body
@classmethod
def create_image(cls, client):
@@ -80,7 +93,7 @@
for resource_id in list_of_ids:
try:
method(resource_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
@classmethod
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
index 97eb4eb..768b6ea 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -10,14 +10,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.telemetry import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class TelemetryAlarmingAPITestJSON(base.BaseTelemetryTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -30,6 +30,7 @@
cls.create_alarm(threshold_rule=cls.rule)
@test.attr(type="gate")
+ @test.idempotent_id('1c918e06-210b-41eb-bd45-14676dd77cd6')
def test_alarm_list(self):
# List alarms
alarm_list = self.telemetry_client.list_alarms()
@@ -43,6 +44,7 @@
', '.join(str(a) for a in missing_alarms))
@test.attr(type="gate")
+ @test.idempotent_id('1297b095-39c1-4e74-8a1f-4ae998cedd67')
def test_create_update_get_delete_alarm(self):
# Create an alarm
alarm_name = data_utils.rand_name('telemetry_alarm')
@@ -70,24 +72,26 @@
self.assertDictContainsSubset(new_rule, body['threshold_rule'])
# Delete alarm and verify if deleted
self.telemetry_client.delete_alarm(alarm_id)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.telemetry_client.get_alarm, alarm_id)
@test.attr(type="gate")
+ @test.idempotent_id('aca49486-70bb-4016-87e0-f6131374f741')
def test_set_get_alarm_state(self):
alarm_states = ['ok', 'alarm', 'insufficient data']
alarm = self.create_alarm(threshold_rule=self.rule)
# Set alarm state and verify
new_state =\
[elem for elem in alarm_states if elem != alarm['state']][0]
- _, state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
- new_state)
- self.assertEqual(new_state, state)
+ state = self.telemetry_client.alarm_set_state(alarm['alarm_id'],
+ new_state)
+ self.assertEqual(new_state, state.data)
# Get alarm state and verify
- _, state = self.telemetry_client.alarm_get_state(alarm['alarm_id'])
- self.assertEqual(new_state, state)
+ state = self.telemetry_client.alarm_get_state(alarm['alarm_id'])
+ self.assertEqual(new_state, state.data)
@test.attr(type="gate")
+ @test.idempotent_id('08d7e45a-1344-4e5c-ba6f-f6cbb77f55b9')
def test_create_delete_alarm_with_combination_rule(self):
rule = {"alarm_ids": self.alarm_ids,
"operator": "or"}
@@ -101,5 +105,5 @@
self.assertDictContainsSubset(rule, body['combination_rule'])
# Verify alarm delete
self.telemetry_client.delete_alarm(alarm_id)
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.telemetry_client.get_alarm, alarm_id)
diff --git a/tempest/api/telemetry/test_telemetry_notification_api.py b/tempest/api/telemetry/test_telemetry_notification_api.py
index 7e5d6ee..6862401 100644
--- a/tempest/api/telemetry/test_telemetry_notification_api.py
+++ b/tempest/api/telemetry/test_telemetry_notification_api.py
@@ -21,22 +21,21 @@
class TelemetryNotificationAPITestJSON(base.BaseTelemetryTest):
- _interface = 'json'
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(TelemetryNotificationAPITestJSON, cls).skip_checks()
if CONF.telemetry.too_slow_to_test:
raise cls.skipException("Ceilometer feature for fast work mysql "
"is disabled")
- super(TelemetryNotificationAPITestJSON, cls).resource_setup()
@test.attr(type="gate")
+ @test.idempotent_id('d7f8c1c8-d470-4731-8604-315d3956caad')
@testtools.skipIf(not CONF.service_available.nova,
"Nova is not available.")
def test_check_nova_notification(self):
- resp, body = self.create_server()
- self.assertEqual(resp.status, 202)
+ body = self.create_server()
query = ('resource', 'eq', body['id'])
@@ -44,6 +43,7 @@
self.await_samples(metric, query)
@test.attr(type="smoke")
+ @test.idempotent_id('04b10bfe-a5dc-47af-b22f-0460426bf498')
@test.services("image")
@testtools.skipIf(not CONF.image_feature_enabled.api_v1,
"Glance api v1 is disabled")
@@ -60,6 +60,7 @@
self.await_samples(metric, query)
@test.attr(type="smoke")
+ @test.idempotent_id('c240457d-d943-439b-8aea-85e26d64fe8e')
@test.services("image")
@testtools.skipIf(not CONF.image_feature_enabled.api_v2,
"Glance api v2 is disabled")
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 65c4bd3..97dd104 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -22,13 +22,17 @@
class VolumeMultiBackendV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumeMultiBackendV2Test, cls).skip_checks()
+
+ if not CONF.volume_feature_enabled.multi_backend:
+ raise cls.skipException("Cinder multi-backend feature disabled")
@classmethod
def resource_setup(cls):
super(VolumeMultiBackendV2Test, cls).resource_setup()
- if not CONF.volume_feature_enabled.multi_backend:
- raise cls.skipException("Cinder multi-backend feature disabled")
cls.backend1_name = CONF.volume.backend1_name
cls.backend2_name = CONF.volume.backend2_name
@@ -97,18 +101,21 @@
super(VolumeMultiBackendV2Test, cls).resource_cleanup()
@test.attr(type='smoke')
+ @test.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
def test_backend_name_reporting(self):
# get volume id which created by type without prefix
volume_id = self.volume_id_list_without_prefix[0]
self._test_backend_name_reporting_by_volume_id(volume_id)
@test.attr(type='smoke')
+ @test.idempotent_id('f38e647f-ab42-4a31-a2e7-ca86a6485215')
def test_backend_name_reporting_with_prefix(self):
# get volume id which created by type with prefix
volume_id = self.volume_id_list_with_prefix[0]
self._test_backend_name_reporting_by_volume_id(volume_id)
@test.attr(type='gate')
+ @test.idempotent_id('46435ab1-a0af-4401-8373-f14e66b0dd58')
def test_backend_name_distinction(self):
if self.backend1_name == self.backend2_name:
raise self.skipException("backends configured with same name")
@@ -118,6 +125,7 @@
self._test_backend_name_distinction(volume1_id, volume2_id)
@test.attr(type='gate')
+ @test.idempotent_id('4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed')
def test_backend_name_distinction_with_prefix(self):
if self.backend1_name == self.backend2_name:
raise self.skipException("backends configured with same name")
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 6c64298..469f13e 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -19,12 +19,15 @@
class SnapshotsActionsV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
+
+ @classmethod
+ def setup_clients(cls):
+ super(SnapshotsActionsV2Test, cls).setup_clients()
+ cls.client = cls.snapshots_client
@classmethod
def resource_setup(cls):
super(SnapshotsActionsV2Test, cls).resource_setup()
- cls.client = cls.snapshots_client
# Create a test shared volume for tests
vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
@@ -78,6 +81,7 @@
return 'os-extended-snapshot-attributes:progress'
@test.attr(type='gate')
+ @test.idempotent_id('3e13ca2f-48ea-49f3-ae1a-488e9180d535')
def test_reset_snapshot_status(self):
# Reset snapshot status to creating
status = 'creating'
@@ -88,6 +92,7 @@
self.assertEqual(status, snapshot_get['status'])
@test.attr(type='gate')
+ @test.idempotent_id('41288afd-d463-485e-8f6e-4eea159413eb')
def test_update_snapshot_status(self):
# Reset snapshot status to creating
status = 'creating'
@@ -106,21 +111,25 @@
self.assertEqual(progress, snapshot_get[progress_alias])
@test.attr(type='gate')
+ @test.idempotent_id('05f711b6-e629-4895-8103-7ca069f2073a')
def test_snapshot_force_delete_when_snapshot_is_creating(self):
# test force delete when status of snapshot is creating
self._create_reset_and_force_delete_temp_snapshot('creating')
@test.attr(type='gate')
+ @test.idempotent_id('92ce8597-b992-43a1-8868-6316b22a969e')
def test_snapshot_force_delete_when_snapshot_is_deleting(self):
# test force delete when status of snapshot is deleting
self._create_reset_and_force_delete_temp_snapshot('deleting')
@test.attr(type='gate')
+ @test.idempotent_id('645a4a67-a1eb-4e8e-a547-600abac1525d')
def test_snapshot_force_delete_when_snapshot_is_error(self):
# test force delete when status of snapshot is error
self._create_reset_and_force_delete_temp_snapshot('error')
@test.attr(type='gate')
+ @test.idempotent_id('bf89080f-8129-465e-9327-b2f922666ba5')
def test_snapshot_force_delete_when_snapshot_is_error_deleting(self):
# test force delete when status of snapshot is error_deleting
self._create_reset_and_force_delete_temp_snapshot('error_deleting')
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index a214edf..551dc6f 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -18,9 +18,9 @@
class VolumeHostsAdminV2TestsJSON(base.BaseVolumeAdminTest):
- _interface = "json"
@test.attr(type='gate')
+ @test.idempotent_id('d5f3efa2-6684-4190-9ced-1c2f526352ad')
def test_list_hosts(self):
hosts = self.hosts_client.list_hosts()
self.assertTrue(len(hosts) >= 2, "No. of hosts are < 2,"
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 52f2d90..27375de 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -1,7 +1,5 @@
# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
#
-# Author: Sylvain Baubeau <sylvain.baubeau@enovance.com>
-#
# 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
@@ -23,21 +21,22 @@
class BaseVolumeQuotasAdminV2TestJSON(base.BaseVolumeAdminTest):
- _interface = "json"
force_tenant_isolation = True
@classmethod
- def resource_setup(cls):
- super(BaseVolumeQuotasAdminV2TestJSON, cls).resource_setup()
+ def setup_credentials(cls):
+ super(BaseVolumeQuotasAdminV2TestJSON, cls).setup_credentials()
cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
@test.attr(type='gate')
+ @test.idempotent_id('59eada70-403c-4cef-a2a3-a8ce2f1b07a0')
def test_list_quotas(self):
quotas = self.quotas_client.get_quota_set(self.demo_tenant_id)
for key in QUOTA_KEYS:
self.assertIn(key, quotas)
@test.attr(type='gate')
+ @test.idempotent_id('2be020a2-5fdd-423d-8d35-a7ffbc36e9f7')
def test_list_default_quotas(self):
quotas = self.quotas_client.get_default_quota_set(
self.demo_tenant_id)
@@ -45,6 +44,7 @@
self.assertIn(key, quotas)
@test.attr(type='gate')
+ @test.idempotent_id('3d45c99e-cc42-4424-a56e-5cbd212b63a6')
def test_update_all_quota_resources_for_tenant(self):
# Admin can update all the resource quota limits for a tenant
default_quota_set = self.quotas_client.get_default_quota_set(
@@ -69,6 +69,7 @@
self.assertDictContainsSubset(new_quota_set, quota_set)
@test.attr(type='gate')
+ @test.idempotent_id('18c51ae9-cb03-48fc-b234-14a19374dbed')
def test_show_quota_usage(self):
quota_usage = self.quotas_client.get_quota_usage(
self.os_adm.credentials.tenant_id)
@@ -78,6 +79,7 @@
self.assertIn(usage_key, quota_usage[key])
@test.attr(type='gate')
+ @test.idempotent_id('ae8b6091-48ad-4bfa-a188-bbf5cc02115f')
def test_quota_usage(self):
quota_usage = self.quotas_client.get_quota_usage(
self.demo_tenant_id)
@@ -96,6 +98,7 @@
new_quota_usage['gigabytes']['in_use'])
@test.attr(type='gate')
+ @test.idempotent_id('874b35a9-51f1-4258-bec5-cd561b6690d3')
def test_delete_quota(self):
# Admin can delete the resource quota set for a tenant
tenant_name = data_utils.rand_name('quota_tenant_')
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 5cf6af0..67edd09 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -13,20 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.volume import base
-from tempest import exceptions
from tempest import test
class BaseVolumeQuotasNegativeV2TestJSON(base.BaseVolumeAdminTest):
- _interface = "json"
force_tenant_isolation = True
@classmethod
+ def setup_credentials(cls):
+ super(BaseVolumeQuotasNegativeV2TestJSON, cls).setup_credentials()
+ cls.demo_user = cls.isolated_creds.get_primary_creds()
+ cls.demo_tenant_id = cls.demo_user.tenant_id
+
+ @classmethod
def resource_setup(cls):
super(BaseVolumeQuotasNegativeV2TestJSON, cls).resource_setup()
- demo_user = cls.isolated_creds.get_primary_creds()
- cls.demo_tenant_id = demo_user.tenant_id
cls.shared_quota_set = {'gigabytes': 3, 'volumes': 1, 'snapshots': 1}
# NOTE(gfidente): no need to restore original quota set
@@ -41,18 +45,21 @@
cls.snapshot = cls.create_snapshot(cls.volume['id'])
@test.attr(type='negative')
+ @test.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
def test_quota_volumes(self):
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.volumes_client.create_volume,
size=1)
@test.attr(type='negative')
+ @test.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
def test_quota_volume_snapshots(self):
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.snapshots_client.create_snapshot,
self.volume['id'])
@test.attr(type='negative')
+ @test.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
def test_quota_volume_gigabytes(self):
# NOTE(gfidente): quota set needs to be changed for this test
# or we may be limited by the volumes or snaps quota number, not by
@@ -65,7 +72,7 @@
self.quotas_client.update_quota_set(
self.demo_tenant_id,
**new_quota_set)
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.volumes_client.create_volume,
size=1)
@@ -73,7 +80,7 @@
self.quotas_client.update_quota_set(
self.demo_tenant_id,
**self.shared_quota_set)
- self.assertRaises(exceptions.OverLimit,
+ self.assertRaises(lib_exc.OverLimit,
self.snapshots_client.create_snapshot,
self.volume['id'])
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 46db70f..cc4f1a0 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -22,7 +22,6 @@
Tests Volume Services API.
volume service list requires admin privileges.
"""
- _interface = "json"
@classmethod
def resource_setup(cls):
@@ -32,11 +31,13 @@
cls.binary_name = cls.services[0]['binary']
@test.attr(type='gate')
+ @test.idempotent_id('e0218299-0a59-4f43-8b2b-f1c035b3d26d')
def test_list_services(self):
services = self.admin_volume_services_client.list_services()
self.assertNotEqual(0, len(services))
@test.attr(type='gate')
+ @test.idempotent_id('63a3e1ca-37ee-4983-826d-83276a370d25')
def test_get_service_by_service_binary_name(self):
params = {'binary': self.binary_name}
services = self.admin_volume_services_client.list_services(params)
@@ -45,6 +46,7 @@
self.assertEqual(self.binary_name, service['binary'])
@test.attr(type='gate')
+ @test.idempotent_id('178710e4-7596-4e08-9333-745cb8bc4f8d')
def test_get_service_by_host_name(self):
services_on_host = [service for service in self.services if
service['host'] == self.host_name]
@@ -61,6 +63,7 @@
self.assertEqual(sorted(s1), sorted(s2))
@test.attr(type='gate')
+ @test.idempotent_id('ffa6167c-4497-4944-a464-226bbdb53908')
def test_get_service_by_service_and_host_name(self):
params = {'host': self.host_name, 'binary': self.binary_name}
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 58f1551..8705f6f 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -22,7 +22,6 @@
class VolumeTypesV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
def _delete_volume(self, volume_id):
self.volumes_client.delete_volume(volume_id)
@@ -32,53 +31,65 @@
self.volume_types_client.delete_volume_type(volume_type_id)
@test.attr(type='smoke')
+ @test.idempotent_id('9d9b28e3-1b2e-4483-a2cc-24aa0ea1de54')
def test_volume_type_list(self):
# List Volume types.
body = self.volume_types_client.list_volume_types()
self.assertIsInstance(body, list)
@test.attr(type='smoke')
- def test_create_get_delete_volume_with_volume_type_and_extra_specs(self):
- # Create/get/delete volume with volume_type and extra spec.
- volume = {}
+ @test.idempotent_id('c03cc62c-f4e9-4623-91ec-64ce2f9c1260')
+ def test_volume_crud_with_volume_type_and_extra_specs(self):
+ # Create/update/get/delete volume with volume_type and extra spec.
+ volume_types = list()
vol_name = data_utils.rand_name("volume-")
- vol_type_name = data_utils.rand_name("volume-type-")
self.name_field = self.special_fields['name_field']
proto = CONF.volume.storage_protocol
vendor = CONF.volume.vendor_name
extra_specs = {"storage_protocol": proto,
"vendor_name": vendor}
- body = {}
- body = self.volume_types_client.create_volume_type(
- vol_type_name,
- extra_specs=extra_specs)
- self.assertIn('id', body)
- self.addCleanup(self._delete_volume_type, body['id'])
- self.assertIn('name', body)
- params = {self.name_field: vol_name, 'volume_type': vol_type_name}
- volume = self.volumes_client.create_volume(
- size=1, **params)
- self.assertIn('id', volume)
+ # Create two volume_types
+ for i in range(2):
+ vol_type_name = data_utils.rand_name("volume-type-")
+ vol_type = self.volume_types_client.create_volume_type(
+ vol_type_name,
+ extra_specs=extra_specs)
+ volume_types.append(vol_type)
+ self.addCleanup(self._delete_volume_type, vol_type['id'])
+ params = {self.name_field: vol_name,
+ 'volume_type': volume_types[0]['id']}
+
+ # Create volume
+ volume = self.volumes_client.create_volume(size=1, **params)
self.addCleanup(self._delete_volume, volume['id'])
- self.assertIn(self.name_field, volume)
+ self.assertEqual(volume_types[0]['name'], volume["volume_type"])
self.assertEqual(volume[self.name_field], vol_name,
"The created volume name is not equal "
"to the requested name")
- self.assertTrue(volume['id'] is not None,
- "Field volume id is empty or not found.")
+ self.assertIsNotNone(volume['id'],
+ "Field volume id is empty or not found.")
self.volumes_client.wait_for_volume_status(volume['id'], 'available')
+
+ # Update volume with new volume_type
+ self.volumes_client.retype_volume(volume['id'],
+ volume_type=volume_types[1]['id'])
+ self.volumes_client.wait_for_volume_status(volume['id'], 'available')
+
+ # Get volume details and Verify
fetched_volume = self.volumes_client.get_volume(volume['id'])
+ self.assertEqual(volume_types[1]['name'],
+ fetched_volume['volume_type'],
+ 'The fetched Volume type is different '
+ 'from updated volume type')
self.assertEqual(vol_name, fetched_volume[self.name_field],
'The fetched Volume is different '
'from the created Volume')
self.assertEqual(volume['id'], fetched_volume['id'],
'The fetched Volume is different '
'from the created Volume')
- self.assertEqual(vol_type_name, fetched_volume['volume_type'],
- 'The fetched Volume is different '
- 'from the created Volume')
@test.attr(type='smoke')
+ @test.idempotent_id('4e955c3b-49db-4515-9590-0c99f8e471ad')
def test_volume_type_create_get_delete(self):
# Create/get volume type.
body = {}
@@ -111,6 +122,7 @@
'from the created Volume_type')
@test.attr(type='smoke')
+ @test.idempotent_id('7830abd0-ff99-4793-a265-405684a54d46')
def test_volume_type_encryption_create_get_delete(self):
# Create/get/delete encryption type.
provider = "LuksEncryptor"
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 460a6c3..5ca838e 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -19,7 +19,6 @@
class VolumeTypesExtraSpecsV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
@classmethod
def resource_setup(cls):
@@ -34,6 +33,7 @@
super(VolumeTypesExtraSpecsV2Test, cls).resource_cleanup()
@test.attr(type='smoke')
+ @test.idempotent_id('b42923e9-0452-4945-be5b-d362ae533e60')
def test_volume_type_extra_specs_list(self):
# List Volume types extra specs.
extra_specs = {"spec1": "val1"}
@@ -47,6 +47,7 @@
self.assertIn('spec1', body)
@test.attr(type='gate')
+ @test.idempotent_id('0806db36-b4a0-47a1-b6f3-c2e7f194d017')
def test_volume_type_extra_specs_update(self):
# Update volume type extra specs
extra_specs = {"spec2": "val1"}
@@ -65,6 +66,7 @@
"Volume type extra spec incorrectly updated")
@test.attr(type='smoke')
+ @test.idempotent_id('d4772798-601f-408a-b2a5-29e8a59d1220')
def test_volume_type_extra_spec_create_get_delete(self):
# Create/Get/Delete volume type extra spec.
extra_specs = {"spec3": "val1"}
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index fff0199..6d2c4fb 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -15,14 +15,14 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.volume import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class ExtraSpecsNegativeV2Test(base.BaseVolumeAdminTest):
- _interface = 'json'
@classmethod
def resource_setup(cls):
@@ -39,103 +39,114 @@
super(ExtraSpecsNegativeV2Test, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('08961d20-5cbb-4910-ac0f-89ad6dbb2da1')
def test_update_no_body(self):
# Should not update volume type extra specs with no body
extra_spec = {"spec1": "val2"}
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.update_volume_type_extra_specs,
self.volume_type['id'], extra_spec.keys()[0], None)
@test.attr(type='gate')
+ @test.idempotent_id('25e5a0ee-89b3-4c53-8310-236f76c75365')
def test_update_nonexistent_extra_spec_id(self):
# Should not update volume type extra specs with nonexistent id.
extra_spec = {"spec1": "val2"}
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.update_volume_type_extra_specs,
self.volume_type['id'], str(uuid.uuid4()),
extra_spec)
@test.attr(type='gate')
+ @test.idempotent_id('9bf7a657-b011-4aec-866d-81c496fbe5c8')
def test_update_none_extra_spec_id(self):
# Should not update volume type extra specs with none id.
extra_spec = {"spec1": "val2"}
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.update_volume_type_extra_specs,
self.volume_type['id'], None, extra_spec)
@test.attr(type='gate')
+ @test.idempotent_id('a77dfda2-9100-448e-9076-ed1711f4bdfc')
def test_update_multiple_extra_spec(self):
# Should not update volume type extra specs with multiple specs as
# body.
extra_spec = {"spec1": "val2", 'spec2': 'val1'}
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.update_volume_type_extra_specs,
self.volume_type['id'], extra_spec.keys()[0],
extra_spec)
@test.attr(type='gate')
+ @test.idempotent_id('49d5472c-a53d-4eab-a4d3-450c4db1c545')
def test_create_nonexistent_type_id(self):
# Should not create volume type extra spec for nonexistent volume
# type id.
extra_specs = {"spec2": "val1"}
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.volume_types_client.create_volume_type_extra_specs,
str(uuid.uuid4()), extra_specs)
@test.attr(type='gate')
+ @test.idempotent_id('c821bdc8-43a4-4bf4-86c8-82f3858d5f7d')
def test_create_none_body(self):
# Should not create volume type extra spec for none POST body.
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.create_volume_type_extra_specs,
self.volume_type['id'], None)
@test.attr(type='gate')
+ @test.idempotent_id('bc772c71-1ed4-4716-b945-8b5ed0f15e87')
def test_create_invalid_body(self):
# Should not create volume type extra spec for invalid POST body.
self.assertRaises(
- exceptions.BadRequest,
+ lib_exc.BadRequest,
self.volume_types_client.create_volume_type_extra_specs,
self.volume_type['id'], ['invalid'])
@test.attr(type='gate')
+ @test.idempotent_id('031cda8b-7d23-4246-8bf6-bbe73fd67074')
def test_delete_nonexistent_volume_type_id(self):
# Should not delete volume type extra spec for nonexistent
# type id.
extra_specs = {"spec1": "val1"}
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.volume_types_client.delete_volume_type_extra_specs,
str(uuid.uuid4()), extra_specs.keys()[0])
@test.attr(type='gate')
+ @test.idempotent_id('dee5cf0c-cdd6-4353-b70c-e847050d71fb')
def test_list_nonexistent_volume_type_id(self):
# Should not list volume type extra spec for nonexistent type id.
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.volume_types_client.list_volume_types_extra_specs,
str(uuid.uuid4()))
@test.attr(type='gate')
+ @test.idempotent_id('9f402cbd-1838-4eb4-9554-126a6b1908c9')
def test_get_nonexistent_volume_type_id(self):
# Should not get volume type extra spec for nonexistent type id.
extra_specs = {"spec1": "val1"}
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.volume_types_client.get_volume_type_extra_specs,
str(uuid.uuid4()), extra_specs.keys()[0])
@test.attr(type='gate')
+ @test.idempotent_id('c881797d-12ff-4f1a-b09d-9f6212159753')
def test_get_nonexistent_extra_spec_id(self):
# Should not get volume type extra spec for nonexistent extra spec
# id.
self.assertRaises(
- exceptions.NotFound,
+ lib_exc.NotFound,
self.volume_types_client.get_volume_type_extra_specs,
self.volume_type['id'], str(uuid.uuid4()))
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 4144270..eb46a54 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -15,41 +15,45 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.volume import base
-from tempest import exceptions
from tempest import test
class VolumeTypesNegativeV2Test(base.BaseVolumeAdminTest):
- _interface = 'json'
@test.attr(type='gate')
+ @test.idempotent_id('b48c98f2-e662-4885-9b71-032256906314')
def test_create_with_nonexistent_volume_type(self):
# Should not be able to create volume with nonexistent volume_type.
self.name_field = self.special_fields['name_field']
params = {self.name_field: str(uuid.uuid4()),
'volume_type': str(uuid.uuid4())}
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.volumes_client.create_volume, size=1,
**params)
@test.attr(type='gate')
+ @test.idempotent_id('878b4e57-faa2-4659-b0d1-ce740a06ae81')
def test_create_with_empty_name(self):
# Should not be able to create volume type with an empty name.
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.volume_types_client.create_volume_type, '')
@test.attr(type='gate')
+ @test.idempotent_id('994610d6-0476-4018-a644-a2602ef5d4aa')
def test_get_nonexistent_type_id(self):
# Should not be able to get volume type with nonexistent type id.
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.volume_types_client.get_volume_type,
str(uuid.uuid4()))
@test.attr(type='gate')
+ @test.idempotent_id('6b3926d2-7d73-4896-bc3d-e42dfd11a9f6')
def test_delete_nonexistent_type_id(self):
# Should not be able to delete volume type with nonexistent type id.
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.volume_types_client.delete_volume_type,
str(uuid.uuid4()))
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 4feba73..b0013e6 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -19,12 +19,15 @@
class VolumesActionsV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
+
+ @classmethod
+ def setup_clients(cls):
+ super(VolumesActionsV2Test, cls).setup_clients()
+ cls.client = cls.volumes_client
@classmethod
def resource_setup(cls):
super(VolumesActionsV2Test, cls).resource_setup()
- cls.client = cls.volumes_client
# Create a test shared volume for tests
vol_name = utils.rand_name(cls.__name__ + '-Volume-')
@@ -73,6 +76,7 @@
self.client.wait_for_resource_deletion(temp_volume['id'])
@test.attr(type='gate')
+ @test.idempotent_id('d063f96e-a2e0-4f34-8b8a-395c42de1845')
def test_volume_reset_status(self):
# test volume reset status : available->error->available
self._reset_volume_status(self.volume['id'], 'error')
@@ -80,15 +84,18 @@
self.volume['id'])
self.assertEqual('error', volume_get['status'])
+ @test.idempotent_id('21737d5a-92f2-46d7-b009-a0cc0ee7a570')
def test_volume_force_delete_when_volume_is_creating(self):
# test force delete when status of volume is creating
self._create_reset_and_force_delete_temp_volume('creating')
+ @test.idempotent_id('db8d607a-aa2e-4beb-b51d-d4005c232011')
def test_volume_force_delete_when_volume_is_attaching(self):
# test force delete when status of volume is attaching
self._create_reset_and_force_delete_temp_volume('attaching')
@test.attr(type='gate')
+ @test.idempotent_id('3e33a8a8-afd4-4d64-a86b-c27a185c5a4a')
def test_volume_force_delete_when_volume_is_error(self):
# test force delete when status of volume is error
self._create_reset_and_force_delete_temp_volume('error')
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 0739480..6b0580f 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -24,18 +24,21 @@
class VolumesBackupsV2Test(base.BaseVolumeAdminTest):
- _interface = "json"
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesBackupsV2Test, cls).skip_checks()
+ if not CONF.volume_feature_enabled.backup:
+ raise cls.skipException("Cinder backup feature disabled")
@classmethod
def resource_setup(cls):
super(VolumesBackupsV2Test, cls).resource_setup()
- if not CONF.volume_feature_enabled.backup:
- raise cls.skipException("Cinder backup feature disabled")
-
cls.volume = cls.create_volume()
@test.attr(type='smoke')
+ @test.idempotent_id('a66eb488-8ee1-47d4-8e9f-575a095728c6')
def test_volume_backup_create_get_detailed_list_restore_delete(self):
# Create backup
backup_name = data_utils.rand_name('Backup')
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 127a216..c672607 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest_lib import exceptions as lib_exc
+
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
@@ -29,31 +31,39 @@
"""Base test case class for all Cinder API tests."""
_api_version = 2
- _interface = 'json'
@classmethod
- def resource_setup(cls):
- cls.set_network_resources()
- super(BaseVolumeTest, cls).resource_setup()
+ def skip_checks(cls):
+ super(BaseVolumeTest, 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)
-
- cls.os = cls.get_client_manager()
-
- cls.servers_client = cls.os.servers_client
- cls.image_ref = CONF.compute.image_ref
- cls.flavor_ref = CONF.compute.flavor_ref
- cls.build_interval = CONF.volume.build_interval
- cls.build_timeout = CONF.volume.build_timeout
- cls.snapshots = []
- cls.volumes = []
-
if cls._api_version == 1:
if not CONF.volume_feature_enabled.api_v1:
msg = "Volume API v1 is disabled"
raise cls.skipException(msg)
+ elif cls._api_version == 2:
+ if not CONF.volume_feature_enabled.api_v2:
+ msg = "Volume API v2 is disabled"
+ raise cls.skipException(msg)
+ else:
+ msg = ("Invalid Cinder API version (%s)" % cls._api_version)
+ raise exceptions.InvalidConfiguration(message=msg)
+
+ @classmethod
+ def setup_credentials(cls):
+ cls.set_network_resources()
+ super(BaseVolumeTest, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
+
+ @classmethod
+ def setup_clients(cls):
+ super(BaseVolumeTest, cls).setup_clients()
+
+ cls.servers_client = cls.os.servers_client
+
+ if cls._api_version == 1:
cls.snapshots_client = cls.os.snapshots_client
cls.volumes_client = cls.os.volumes_client
cls.backups_client = cls.os.backups_client
@@ -61,27 +71,33 @@
cls.volumes_extension_client = cls.os.volumes_extension_client
cls.availability_zone_client = (
cls.os.volume_availability_zone_client)
- # Special fields and resp code for cinder v1
- cls.special_fields = {'name_field': 'display_name',
- 'descrip_field': 'display_description'}
-
- elif cls._api_version == 2:
- if not CONF.volume_feature_enabled.api_v2:
- msg = "Volume API v2 is disabled"
- raise cls.skipException(msg)
+ else:
cls.snapshots_client = cls.os.snapshots_v2_client
cls.volumes_client = cls.os.volumes_v2_client
cls.volumes_extension_client = cls.os.volumes_v2_extension_client
cls.availability_zone_client = (
cls.os.volume_v2_availability_zone_client)
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseVolumeTest, cls).resource_setup()
+
+ cls.snapshots = []
+ cls.volumes = []
+ cls.image_ref = CONF.compute.image_ref
+ cls.flavor_ref = CONF.compute.flavor_ref
+ cls.build_interval = CONF.volume.build_interval
+ cls.build_timeout = CONF.volume.build_timeout
+
+ if cls._api_version == 1:
+ # Special fields and resp code for cinder v1
+ cls.special_fields = {'name_field': 'display_name',
+ 'descrip_field': 'display_description'}
+ else:
# Special fields and resp code for cinder v2
cls.special_fields = {'name_field': 'name',
'descrip_field': 'description'}
- else:
- msg = ("Invalid Cinder API version (%s)" % cls._api_version)
- raise exceptions.InvalidConfiguration(message=msg)
-
@classmethod
def resource_cleanup(cls):
cls.clear_snapshots()
@@ -147,24 +163,22 @@
class BaseVolumeAdminTest(BaseVolumeTest):
"""Base test case class for all Volume Admin API tests."""
- @classmethod
- def resource_setup(cls):
- super(BaseVolumeAdminTest, cls).resource_setup()
+ @classmethod
+ def setup_credentials(cls):
+ super(BaseVolumeAdminTest, cls).setup_credentials()
try:
cls.adm_creds = cls.isolated_creds.get_admin_creds()
- cls.os_adm = clients.Manager(
- credentials=cls.adm_creds, interface=cls._interface)
+ cls.os_adm = clients.Manager(credentials=cls.adm_creds)
except NotImplementedError:
msg = "Missing Volume Admin API credentials in configuration."
raise cls.skipException(msg)
- cls.qos_specs = []
+ @classmethod
+ def setup_clients(cls):
+ super(BaseVolumeAdminTest, cls).setup_clients()
if cls._api_version == 1:
- if not CONF.volume_feature_enabled.api_v1:
- msg = "Volume API v1 is disabled"
- raise cls.skipException(msg)
cls.volume_qos_client = cls.os_adm.volume_qos_client
cls.admin_volume_services_client = \
cls.os_adm.volume_services_client
@@ -175,9 +189,6 @@
cls.backups_adm_client = cls.os_adm.backups_client
cls.quotas_client = cls.os_adm.volume_quotas_client
elif cls._api_version == 2:
- if not CONF.volume_feature_enabled.api_v2:
- msg = "Volume API v2 is disabled"
- raise cls.skipException(msg)
cls.volume_qos_client = cls.os_adm.volume_qos_v2_client
cls.admin_volume_services_client = \
cls.os_adm.volume_services_v2_client
@@ -189,6 +200,12 @@
cls.quotas_client = cls.os_adm.volume_quotas_v2_client
@classmethod
+ def resource_setup(cls):
+ super(BaseVolumeAdminTest, cls).resource_setup()
+
+ cls.qos_specs = []
+
+ @classmethod
def resource_cleanup(cls):
cls.clear_qos_specs()
super(BaseVolumeAdminTest, cls).resource_cleanup()
@@ -208,13 +225,13 @@
for qos_id in cls.qos_specs:
try:
cls.volume_qos_client.delete_qos(qos_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# The qos_specs may have already been deleted which is OK.
pass
for qos_id in cls.qos_specs:
try:
cls.volume_qos_client.wait_for_resource_deletion(qos_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# The qos_specs may have already been deleted which is OK.
pass
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index bd3d2a1..e63cfcd 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -24,11 +24,12 @@
"""
@classmethod
- def resource_setup(cls):
- super(AvailabilityZoneV2TestJSON, cls).resource_setup()
+ def setup_clients(cls):
+ super(AvailabilityZoneV2TestJSON, cls).setup_clients()
cls.client = cls.availability_zone_client
@test.attr(type='gate')
+ @test.idempotent_id('01f1ae88-eba9-4c6b-a011-6f7ace06b725')
def test_get_availability_zone_list(self):
# List of availability zone
availability_zone = self.client.get_availability_zone_list()
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index dbbdea4..e5fe3c8 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -28,6 +28,7 @@
class ExtensionsV2TestJSON(base.BaseVolumeTest):
@test.attr(type='gate')
+ @test.idempotent_id('94607eb0-43a5-47ca-82aa-736b41bd2e2c')
def test_list_extensions(self):
# List of all extensions
extensions = self.volumes_extension_client.list_extensions()
diff --git a/tempest/api/volume/test_qos.py b/tempest/api/volume/test_qos.py
index 60c327b..b08a019 100644
--- a/tempest/api/volume/test_qos.py
+++ b/tempest/api/volume/test_qos.py
@@ -72,6 +72,7 @@
return associations
+ @test.idempotent_id('7e15f883-4bef-49a9-95eb-f94209a1ced1')
def test_create_delete_qos_with_front_end_consumer(self):
"""Tests the creation and deletion of QoS specs
@@ -79,6 +80,7 @@
"""
self._create_delete_test_qos_with_given_consumer('front-end')
+ @test.idempotent_id('b115cded-8f58-4ee4-aab5-9192cfada08f')
def test_create_delete_qos_with_back_end_consumer(self):
"""Tests the creation and deletion of QoS specs
@@ -87,6 +89,7 @@
self._create_delete_test_qos_with_given_consumer('back-end')
@test.attr(type='smoke')
+ @test.idempotent_id('f88d65eb-ea0d-487d-af8d-71f4011575a4')
def test_create_delete_qos_with_both_consumer(self):
"""Tests the creation and deletion of QoS specs
@@ -95,6 +98,7 @@
self._create_delete_test_qos_with_given_consumer('both')
@test.attr(type='smoke')
+ @test.idempotent_id('7aa214cc-ac1a-4397-931f-3bb2e83bb0fd')
def test_get_qos(self):
"""Tests the detail of a given qos-specs"""
body = self.volume_qos_client.get_qos(self.created_qos['id'])
@@ -102,12 +106,14 @@
self.assertEqual(self.qos_consumer, body['consumer'])
@test.attr(type='smoke')
+ @test.idempotent_id('75e04226-bcf7-4595-a34b-fdf0736f38fc')
def test_list_qos(self):
"""Tests the list of all qos-specs"""
body = self.volume_qos_client.list_qos()
self.assertIn(self.created_qos, body)
@test.attr(type='smoke')
+ @test.idempotent_id('ed00fd85-4494-45f2-8ceb-9e2048919aed')
def test_set_unset_qos_key(self):
"""Test the addition of a specs key to qos-specs"""
args = {'iops_bytes': '500'}
@@ -127,6 +133,7 @@
self.assertNotIn(keys[0], body['specs'])
@test.attr(type='smoke')
+ @test.idempotent_id('1dd93c76-6420-485d-a771-874044c416ac')
def test_associate_disassociate_qos(self):
"""Test the following operations :
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index 03474ba..d4efc2a 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -20,9 +20,13 @@
class SnapshotV2MetadataTestJSON(base.BaseVolumeTest):
@classmethod
+ def setup_clients(cls):
+ super(SnapshotV2MetadataTestJSON, cls).setup_clients()
+ cls.client = cls.snapshots_client
+
+ @classmethod
def resource_setup(cls):
super(SnapshotV2MetadataTestJSON, cls).resource_setup()
- cls.client = cls.snapshots_client
# Create a volume
cls.volume = cls.create_volume()
# Create a snapshot
@@ -35,6 +39,7 @@
super(SnapshotV2MetadataTestJSON, self).tearDown()
@test.attr(type='gate')
+ @test.idempotent_id('a2f20f99-e363-4584-be97-bc33afb1a56c')
def test_create_get_delete_snapshot_metadata(self):
# Create metadata for the snapshot
metadata = {"key1": "value1",
@@ -54,6 +59,7 @@
self.assertEqual(expected, body)
@test.attr(type='gate')
+ @test.idempotent_id('bd2363bc-de92-48a4-bc98-28943c6e4be1')
def test_update_snapshot_metadata(self):
# Update metadata for the snapshot
metadata = {"key1": "value1",
@@ -75,6 +81,7 @@
self.assertEqual(update, body)
@test.attr(type='gate')
+ @test.idempotent_id('e8ff85c5-8f97-477f-806a-3ac364a949ed')
def test_update_snapshot_metadata_item(self):
# Update metadata item for the snapshot
metadata = {"key1": "value1",
diff --git a/tempest/api/volume/test_volume_metadata.py b/tempest/api/volume/test_volume_metadata.py
index 4739fd2..e601349 100644
--- a/tempest/api/volume/test_volume_metadata.py
+++ b/tempest/api/volume/test_volume_metadata.py
@@ -34,6 +34,7 @@
super(VolumesV2MetadataTest, self).tearDown()
@test.attr(type='gate')
+ @test.idempotent_id('6f5b125b-f664-44bf-910f-751591fe5769')
def test_create_get_delete_volume_metadata(self):
# Create metadata for the volume
metadata = {"key1": "value1",
@@ -55,6 +56,7 @@
self.assertThat(body.items(), matchers.ContainsAll(metadata.items()))
@test.attr(type='gate')
+ @test.idempotent_id('774d2918-9beb-4f30-b3d1-2a4e8179ec0a')
def test_update_volume_metadata(self):
# Update metadata for the volume
metadata = {"key1": "value1",
@@ -78,6 +80,7 @@
self.assertThat(body.items(), matchers.ContainsAll(update.items()))
@test.attr(type='gate')
+ @test.idempotent_id('862261c5-8df4-475a-8c21-946e50e36a20')
def test_update_volume_metadata_item(self):
# Update metadata item for the volume
metadata = {"key1": "value1",
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index b2961bd..40947df 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -17,6 +17,7 @@
from tempest.api.volume import base
from tempest import clients
+from tempest.common import credentials
from tempest import config
from tempest import test
@@ -26,21 +27,25 @@
class VolumesV2TransfersTest(base.BaseVolumeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesV2TransfersTest, cls).resource_setup()
-
- # Add another tenant to test volume-transfer
- cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds(),
- interface=cls._interface)
- # Add admin tenant to cleanup resources
- try:
- creds = cls.isolated_creds.get_admin_creds()
- cls.os_adm = clients.Manager(
- credentials=creds, interface=cls._interface)
- except NotImplementedError:
+ def skip_checks(cls):
+ super(VolumesV2TransfersTest, cls).skip_checks()
+ if not credentials.is_admin_available():
msg = "Missing Volume Admin API credentials in configuration."
raise cls.skipException(msg)
+ @classmethod
+ def setup_credentials(cls):
+ super(VolumesV2TransfersTest, cls).setup_credentials()
+ # Add another tenant to test volume-transfer
+ cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
+ # Add admin tenant to cleanup resources
+ creds = cls.isolated_creds.get_admin_creds()
+ cls.os_adm = clients.Manager(credentials=creds)
+
+ @classmethod
+ def setup_clients(cls):
+ super(VolumesV2TransfersTest, cls).setup_clients()
+
cls.client = cls.volumes_client
cls.alt_client = cls.os_alt.volumes_client
cls.alt_tenant_id = cls.alt_client.tenant_id
@@ -52,6 +57,7 @@
self.adm_client.wait_for_resource_deletion(volume_id)
@test.attr(type='gate')
+ @test.idempotent_id('4d75b645-a478-48b1-97c8-503f64242f1a')
def test_create_get_list_accept_volume_transfer(self):
# Create a volume first
volume = self.create_volume()
@@ -78,6 +84,7 @@
auth_key)
self.alt_client.wait_for_volume_status(volume['id'], 'available')
+ @test.idempotent_id('ab526943-b725-4c07-b875-8e8ef87a2c30')
def test_create_list_delete_volume_transfer(self):
# Create a volume first
volume = self.create_volume()
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index ceabb1c..5cad6b4 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -24,20 +24,25 @@
class VolumesV2ActionsTest(base.BaseVolumeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesV2ActionsTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(VolumesV2ActionsTest, cls).setup_clients()
cls.client = cls.volumes_client
cls.image_client = cls.os.image_client
+ @classmethod
+ def resource_setup(cls):
+ super(VolumesV2ActionsTest, cls).resource_setup()
+
# Create a test shared instance
srv_name = data_utils.rand_name(cls.__name__ + '-Instance-')
- resp, cls.server = cls.servers_client.create_server(srv_name,
- cls.image_ref,
- cls.flavor_ref)
+ cls.server = cls.servers_client.create_server(srv_name,
+ cls.image_ref,
+ cls.flavor_ref)
cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')
# Create a test shared volume for attach/detach tests
cls.volume = cls.create_volume()
+ cls.client.wait_for_volume_status(cls.volume['id'], 'available')
def _delete_image_with_wait(self, image_id):
self.image_client.delete_image(image_id)
@@ -51,6 +56,7 @@
super(VolumesV2ActionsTest, cls).resource_cleanup()
+ @test.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d')
@test.stresstest(class_setup_per='process')
@test.attr(type='smoke')
@test.services('compute')
@@ -64,6 +70,7 @@
self.client.detach_volume(self.volume['id'])
self.client.wait_for_volume_status(self.volume['id'], 'available')
+ @test.idempotent_id('9516a2c8-9135-488c-8dd6-5677a7e5f371')
@test.stresstest(class_setup_per='process')
@test.attr(type='gate')
@test.services('compute')
@@ -89,6 +96,7 @@
self.assertEqual(self.volume['id'], attachment['volume_id'])
@test.attr(type='gate')
+ @test.idempotent_id('d8f1ca95-3d5b-44a3-b8ca-909691c9532d')
@test.services('image')
def test_volume_upload(self):
# NOTE(gfidente): the volume uploaded in Glance comes from setUpClass,
@@ -105,6 +113,7 @@
self.client.wait_for_volume_status(self.volume['id'], 'available')
@test.attr(type='gate')
+ @test.idempotent_id('92c4ef64-51b2-40c0-9f7e-4749fbaaba33')
def test_reserve_unreserve_volume(self):
# Mark volume as reserved.
body = self.client.reserve_volume(self.volume['id'])
@@ -121,6 +130,7 @@
return val in ['true', 'True', True]
@test.attr(type='gate')
+ @test.idempotent_id('fff74e1e-5bd3-4b33-9ea9-24c103bc3f59')
def test_volume_readonly_update(self):
# Update volume readonly true
readonly = True
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index ebe6084..35c12bc 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -23,11 +23,12 @@
class VolumesV2ExtendTest(base.BaseVolumeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesV2ExtendTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(VolumesV2ExtendTest, cls).setup_clients()
cls.client = cls.volumes_client
@test.attr(type='gate')
+ @test.idempotent_id('9a36df71-a257-43a5-9555-dc7c88e66e0e')
def test_volume_extend(self):
# Extend Volume Test.
self.volume = self.create_volume()
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 6d9c438..007b0db 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -26,9 +26,13 @@
class VolumesV2GetTest(base.BaseVolumeTest):
@classmethod
+ def setup_clients(cls):
+ super(VolumesV2GetTest, cls).setup_clients()
+ cls.client = cls.volumes_client
+
+ @classmethod
def resource_setup(cls):
super(VolumesV2GetTest, cls).resource_setup()
- cls.client = cls.volumes_client
cls.name_field = cls.special_fields['name_field']
cls.descrip_field = cls.special_fields['descrip_field']
@@ -37,15 +41,6 @@
self.client.delete_volume(volume_id)
self.client.wait_for_resource_deletion(volume_id)
- def _is_true(self, val):
- # NOTE(jdg): Temporary conversion method to get cinder patch
- # merged. Then we'll make this strict again and
- # specifically check "true" or "false"
- if val in ['true', 'True', True]:
- return True
- else:
- return False
-
def _volume_create_get_update_delete(self, **kwargs):
# Create a volume, Get it's details and Delete the volume
volume = {}
@@ -79,13 +74,10 @@
'The fetched Volume metadata misses data '
'from the created Volume')
- # NOTE(jdg): Revert back to strict true/false checking
- # after fix for bug #1227837 merges
- boot_flag = self._is_true(fetched_volume['bootable'])
if 'imageRef' in kwargs:
- self.assertEqual(boot_flag, True)
+ self.assertEqual('true', fetched_volume['bootable'])
if 'imageRef' not in kwargs:
- self.assertEqual(boot_flag, False)
+ self.assertEqual('false', fetched_volume['bootable'])
# Update Volume
# Test volume update when display_name is same with original value
@@ -125,24 +117,24 @@
self.descrip_field: volume[self.descrip_field]}
self.client.update_volume(new_volume['id'], **params)
- # NOTE(jdg): Revert back to strict true/false checking
- # after fix for bug #1227837 merges
- boot_flag = self._is_true(updated_volume['bootable'])
if 'imageRef' in kwargs:
- self.assertEqual(boot_flag, True)
+ self.assertEqual('true', updated_volume['bootable'])
if 'imageRef' not in kwargs:
- self.assertEqual(boot_flag, False)
+ self.assertEqual('false', updated_volume['bootable'])
@test.attr(type='smoke')
+ @test.idempotent_id('27fb0e9f-fb64-41dd-8bdb-1ffa762f0d51')
def test_volume_create_get_update_delete(self):
self._volume_create_get_update_delete()
@test.attr(type='smoke')
+ @test.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
@test.services('image')
def test_volume_create_get_update_delete_from_image(self):
self._volume_create_get_update_delete(imageRef=CONF.compute.image_ref)
@test.attr(type='gate')
+ @test.idempotent_id('3f591b4a-7dc6-444c-bd51-77469506b3a1')
def test_volume_create_get_update_delete_as_clone(self):
origin = self.create_volume()
self._volume_create_get_update_delete(source_volid=origin['id'])
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 91beae9..ef7cebb 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -55,9 +55,13 @@
[str_vol(v) for v in fetched_list]))
@classmethod
+ def setup_clients(cls):
+ super(VolumesV2ListTestJSON, cls).setup_clients()
+ cls.client = cls.volumes_client
+
+ @classmethod
def resource_setup(cls):
super(VolumesV2ListTestJSON, cls).resource_setup()
- cls.client = cls.volumes_client
cls.name = cls.VOLUME_FIELDS[1]
# Create 3 test volumes
@@ -108,6 +112,7 @@
self.assertEqual(params[key], volume[key], msg)
@test.attr(type='smoke')
+ @test.idempotent_id('0b6ddd39-b948-471f-8038-4787978747c4')
def test_volume_list(self):
# Get a list of Volumes
# Fetch all volumes
@@ -116,6 +121,7 @@
fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
+ @test.idempotent_id('adcbb5a7-5ad8-4b61-bd10-5380e111a877')
def test_volume_list_with_details(self):
# Get a list of Volumes with details
# Fetch all Volumes
@@ -123,6 +129,7 @@
self.assertVolumesIn(fetched_list, self.volume_list)
@test.attr(type='gate')
+ @test.idempotent_id('a28e8da4-0b56-472f-87a8-0f4d3f819c02')
def test_volume_list_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {self.name: volume[self.name]}
@@ -132,6 +139,7 @@
volume[self.name])
@test.attr(type='gate')
+ @test.idempotent_id('2de3a6d4-12aa-403b-a8f2-fdeb42a89623')
def test_volume_list_details_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
params = {self.name: volume[self.name]}
@@ -141,6 +149,7 @@
volume[self.name])
@test.attr(type='gate')
+ @test.idempotent_id('39654e13-734c-4dab-95ce-7613bf8407ce')
def test_volumes_list_by_status(self):
params = {'status': 'available'}
fetched_list = self.client.list_volumes(params)
@@ -149,6 +158,7 @@
fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
+ @test.idempotent_id('2943f712-71ec-482a-bf49-d5ca06216b9f')
def test_volumes_list_details_by_status(self):
params = {'status': 'available'}
fetched_list = self.client.list_volumes_with_detail(params)
@@ -157,6 +167,7 @@
self.assertVolumesIn(fetched_list, self.volume_list)
@test.attr(type='gate')
+ @test.idempotent_id('c0cfa863-3020-40d7-b587-e35f597d5d87')
def test_volumes_list_by_availability_zone(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
@@ -167,6 +178,7 @@
fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
+ @test.idempotent_id('e1b80d13-94f0-4ba2-a40e-386af29f8db1')
def test_volumes_list_details_by_availability_zone(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
zone = volume['availability_zone']
@@ -177,18 +189,21 @@
self.assertVolumesIn(fetched_list, self.volume_list)
@test.attr(type='gate')
+ @test.idempotent_id('b5ebea1b-0603-40a0-bb41-15fcd0a53214')
def test_volume_list_with_param_metadata(self):
# Test to list volumes when metadata param is given
params = {'metadata': self.metadata}
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('1ca92d3c-4a8e-4b43-93f5-e4c7fb3b291d')
def test_volume_list_with_detail_param_metadata(self):
# Test to list volumes details when metadata param is given
params = {'metadata': self.metadata}
self._list_by_param_value_and_assert(params, with_detail=True)
@test.attr(type='gate')
+ @test.idempotent_id('777c87c1-2fc4-4883-8b8e-5c0b951d1ec8')
def test_volume_list_param_display_name_and_status(self):
# Test to list volume when display name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
@@ -197,6 +212,7 @@
self._list_by_param_value_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('856ab8ca-6009-4c37-b691-be1065528ad4')
def test_volume_list_with_detail_param_display_name_and_status(self):
# Test to list volume when name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index dc8d8e2..27fd495 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -15,18 +15,23 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.volume import base
from tempest.common.utils import data_utils
-from tempest import exceptions
from tempest import test
class VolumesV2NegativeTest(base.BaseVolumeTest):
@classmethod
+ def setup_clients(cls):
+ super(VolumesV2NegativeTest, cls).setup_clients()
+ cls.client = cls.volumes_client
+
+ @classmethod
def resource_setup(cls):
super(VolumesV2NegativeTest, cls).resource_setup()
- cls.client = cls.volumes_client
cls.name_field = cls.special_fields['name_field']
@@ -35,204 +40,231 @@
cls.mountpoint = "/dev/vdc"
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f131c586-9448-44a4-a8b0-54ca838aa43e')
def test_volume_get_nonexistent_volume_id(self):
# Should not be able to get a non-existent volume
- self.assertRaises(exceptions.NotFound, self.client.get_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.get_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('555efa6e-efcd-44ef-8a3b-4a7ca4837a29')
def test_volume_delete_nonexistent_volume_id(self):
# Should not be able to delete a non-existent Volume
- self.assertRaises(exceptions.NotFound, self.client.delete_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1ed83a8a-682d-4dfb-a30e-ee63ffd6c049')
def test_create_volume_with_invalid_size(self):
# Should not be able to create volume with invalid size
# in request
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='#$%', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
def test_create_volume_with_out_passing_size(self):
# Should not be able to create volume without passing size
# in request
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('41331caa-eaf4-4001-869d-bc18c1869360')
def test_create_volume_with_size_zero(self):
# Should not be able to create volume with size zero
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='0', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8b472729-9eba-446e-a83b-916bdb34bef7')
def test_create_volume_with_size_negative(self):
# Should not be able to create volume with size negative
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.BadRequest, self.client.create_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
size='-1', display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('10254ed8-3849-454e-862e-3ab8e6aa01d2')
def test_create_volume_with_nonexistent_volume_type(self):
# Should not be able to create volume with non-existent volume type
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.create_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.create_volume,
size='1', volume_type=str(uuid.uuid4()),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0c36f6ae-4604-4017-b0a9-34fdc63096f9')
def test_create_volume_with_nonexistent_snapshot_id(self):
# Should not be able to create volume with non-existent snapshot
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.create_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.create_volume,
size='1', snapshot_id=str(uuid.uuid4()),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('47c73e08-4be8-45bb-bfdf-0c4e79b88344')
def test_create_volume_with_nonexistent_source_volid(self):
# Should not be able to create volume with non-existent source volume
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.create_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.create_volume,
size='1', source_volid=str(uuid.uuid4()),
display_name=v_name, metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0186422c-999a-480e-a026-6a665744c30c')
def test_update_volume_with_nonexistent_volume_id(self):
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.update_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.update_volume,
volume_id=str(uuid.uuid4()), display_name=v_name,
metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e66e40d6-65e6-4e75-bdc7-636792fa152d')
def test_update_volume_with_invalid_volume_id(self):
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.update_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.update_volume,
volume_id='#$%%&^&^', display_name=v_name,
metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('72aeca85-57a5-4c1f-9057-f320f9ea575b')
def test_update_volume_with_empty_volume_id(self):
v_name = data_utils.rand_name('Volume-')
metadata = {'Type': 'work'}
- self.assertRaises(exceptions.NotFound, self.client.update_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.update_volume,
volume_id='', display_name=v_name,
metadata=metadata)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('30799cfd-7ee4-446c-b66c-45b383ed211b')
def test_get_invalid_volume_id(self):
# Should not be able to get volume with invalid id
- self.assertRaises(exceptions.NotFound, self.client.get_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.get_volume,
'#$%%&^&^')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('c6c3db06-29ad-4e91-beb0-2ab195fe49e3')
def test_get_volume_without_passing_volume_id(self):
# Should not be able to get volume when empty ID is passed
- self.assertRaises(exceptions.NotFound, self.client.get_volume, '')
+ self.assertRaises(lib_exc.NotFound, self.client.get_volume, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('1f035827-7c32-4019-9240-b4ec2dbd9dfd')
def test_delete_invalid_volume_id(self):
# Should not be able to delete volume when invalid ID is passed
- self.assertRaises(exceptions.NotFound, self.client.delete_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
'!@#$%^&*()')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('441a1550-5d44-4b30-af0f-a6d402f52026')
def test_delete_volume_without_passing_volume_id(self):
# Should not be able to delete volume when empty ID is passed
- self.assertRaises(exceptions.NotFound, self.client.delete_volume, '')
+ self.assertRaises(lib_exc.NotFound, self.client.delete_volume, '')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
@test.services('compute')
def test_attach_volumes_with_nonexistent_volume_id(self):
srv_name = data_utils.rand_name('Instance-')
- resp, server = self.servers_client.create_server(srv_name,
- self.image_ref,
- self.flavor_ref)
+ server = self.servers_client.create_server(srv_name,
+ self.image_ref,
+ self.flavor_ref)
self.addCleanup(self.servers_client.delete_server, server['id'])
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.attach_volume,
str(uuid.uuid4()),
server['id'],
self.mountpoint)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9f9c24e4-011d-46b5-b992-952140ce237a')
def test_detach_volumes_with_invalid_volume_id(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.detach_volume,
'xxx')
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e0c75c74-ee34-41a9-9288-2a2051452854')
def test_volume_extend_with_size_smaller_than_original_size(self):
# Extend volume with smaller size than original size.
extend_size = 0
- self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
self.volume['id'], extend_size)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('5d0b480d-e833-439f-8a5a-96ad2ed6f22f')
def test_volume_extend_with_non_number_size(self):
# Extend volume when size is non number.
extend_size = 'abc'
- self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
self.volume['id'], extend_size)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('355218f1-8991-400a-a6bb-971239287d92')
def test_volume_extend_with_None_size(self):
# Extend volume with None size.
extend_size = None
- self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
+ self.assertRaises(lib_exc.BadRequest, self.client.extend_volume,
self.volume['id'], extend_size)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('8f05a943-013c-4063-ac71-7baf561e82eb')
def test_volume_extend_with_nonexistent_volume_id(self):
# Extend volume size when volume is nonexistent.
extend_size = int(self.volume['size']) + 1
- self.assertRaises(exceptions.NotFound, self.client.extend_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
str(uuid.uuid4()), extend_size)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
def test_volume_extend_without_passing_volume_id(self):
# Extend volume size when passing volume id is None.
extend_size = int(self.volume['size']) + 1
- self.assertRaises(exceptions.NotFound, self.client.extend_volume,
+ self.assertRaises(lib_exc.NotFound, self.client.extend_volume,
None, extend_size)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ac6084c0-0546-45f9-b284-38a367e0e0e2')
def test_reserve_volume_with_nonexistent_volume_id(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.reserve_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('eb467654-3dc1-4a72-9b46-47c29d22654c')
def test_unreserve_volume_with_nonexistent_volume_id(self):
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.client.unreserve_volume,
str(uuid.uuid4()))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('449c4ed2-ecdd-47bb-98dc-072aeccf158c')
def test_reserve_volume_with_negative_volume_status(self):
# Mark volume as reserved.
self.client.reserve_volume(self.volume['id'])
# Mark volume which is marked as reserved before
- self.assertRaises(exceptions.BadRequest,
+ self.assertRaises(lib_exc.BadRequest,
self.client.reserve_volume,
self.volume['id'])
# Unmark volume as reserved.
self.client.unreserve_volume(self.volume['id'])
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('0f4aa809-8c7b-418f-8fb3-84c7a5dfc52f')
def test_list_volumes_with_nonexistent_name(self):
v_name = data_utils.rand_name('Volume-')
params = {self.name_field: v_name}
@@ -240,6 +272,7 @@
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('9ca17820-a0e7-4cbd-a7fa-f4468735e359')
def test_list_volumes_detail_with_nonexistent_name(self):
v_name = data_utils.rand_name('Volume-')
params = {self.name_field: v_name}
@@ -248,12 +281,14 @@
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('143b279b-7522-466b-81be-34a87d564a7c')
def test_list_volumes_with_invalid_status(self):
params = {'status': 'null'}
fetched_volume = self.client.list_volumes(params)
self.assertEqual(0, len(fetched_volume))
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('ba94b27b-be3f-496c-a00e-0283b373fa75')
def test_list_volumes_detail_with_invalid_status(self):
params = {'status': 'null'}
fetched_volume = \
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 179eb09..3c1cce3 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -23,13 +23,16 @@
class VolumesV2SnapshotTestJSON(base.BaseVolumeTest):
@classmethod
+ def skip_checks(cls):
+ super(VolumesV2SnapshotTestJSON, cls).skip_checks()
+ if not CONF.volume_feature_enabled.snapshot:
+ raise cls.skipException("Cinder volume snapshots are disabled")
+
+ @classmethod
def resource_setup(cls):
super(VolumesV2SnapshotTestJSON, cls).resource_setup()
cls.volume_origin = cls.create_volume()
- if not CONF.volume_feature_enabled.snapshot:
- raise cls.skipException("Cinder volume snapshots are disabled")
-
cls.name_field = cls.special_fields['name_field']
cls.descrip_field = cls.special_fields['descrip_field']
@@ -59,18 +62,19 @@
self.assertEqual(params[key], snap[key], msg)
@test.attr(type='gate')
+ @test.idempotent_id('b467b54c-07a4-446d-a1cf-651dedcc3ff1')
@test.services('compute')
def test_snapshot_create_with_volume_in_use(self):
# Create a snapshot when volume status is in-use
# Create a test instance
server_name = data_utils.rand_name('instance-')
- resp, server = self.servers_client.create_server(server_name,
- self.image_ref,
- self.flavor_ref)
+ server = self.servers_client.create_server(server_name,
+ self.image_ref,
+ self.flavor_ref)
self.addCleanup(self.servers_client.delete_server, server['id'])
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
mountpoint = '/dev/%s' % CONF.compute.volume_device_name
- _, body = self.servers_client.attach_volume(
+ self.servers_client.attach_volume(
server['id'], self.volume_origin['id'], mountpoint)
self.volumes_client.wait_for_volume_status(self.volume_origin['id'],
'in-use')
@@ -87,6 +91,7 @@
self.snapshots.remove(snapshot)
@test.attr(type='gate')
+ @test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
def test_snapshot_create_get_list_update_delete(self):
# Create a snapshot
s_name = data_utils.rand_name('snap')
@@ -127,6 +132,7 @@
self.snapshots.remove(snapshot)
@test.attr(type='gate')
+ @test.idempotent_id('59f41f43-aebf-48a9-ab5d-d76340fab32b')
def test_snapshots_list_with_params(self):
"""list snapshots with params."""
# Create a snapshot
@@ -148,6 +154,7 @@
self._list_by_param_values_and_assert(params)
@test.attr(type='gate')
+ @test.idempotent_id('220a1022-1fcd-4a74-a7bd-6b859156cda2')
def test_snapshots_list_details_with_params(self):
"""list snapshot details with params."""
# Create a snapshot
@@ -167,6 +174,7 @@
self._list_by_param_values_and_assert(params, with_detail=True)
@test.attr(type='gate')
+ @test.idempotent_id('677863d1-3142-456d-b6ac-9924f667a7f4')
def test_volume_from_snapshot(self):
# Create a temporary snap using wrapper method from base, then
# create a snap based volume and deletes it
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 2d7b6de..fbbc623 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -12,10 +12,11 @@
import uuid
+from tempest_lib import exceptions as lib_exc
+
from tempest.api.volume import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -24,25 +25,26 @@
class VolumesV2SnapshotNegativeTestJSON(base.BaseVolumeTest):
@classmethod
- def resource_setup(cls):
- super(VolumesV2SnapshotNegativeTestJSON, cls).resource_setup()
-
+ def skip_checks(cls):
+ super(VolumesV2SnapshotNegativeTestJSON, cls).skip_checks()
if not CONF.volume_feature_enabled.snapshot:
raise cls.skipException("Cinder volume snapshots are disabled")
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('e3e466af-70ab-4f4b-a967-ab04e3532ea7')
def test_create_snapshot_with_nonexistent_volume_id(self):
# Create a snapshot with nonexistent volume id
s_name = data_utils.rand_name('snap')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.snapshots_client.create_snapshot,
str(uuid.uuid4()), display_name=s_name)
@test.attr(type=['negative', 'gate'])
+ @test.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
def test_create_snapshot_without_passing_volume_id(self):
# Create a snapshot without passing volume id
s_name = data_utils.rand_name('snap')
- self.assertRaises(exceptions.NotFound,
+ self.assertRaises(lib_exc.NotFound,
self.snapshots_client.create_snapshot,
None, display_name=s_name)
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index bc14b2c..f6b52a9 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -31,9 +31,13 @@
"""
@classmethod
+ def setup_clients(cls):
+ super(VolumesV2ListTestJSON, cls).setup_clients()
+ cls.client = cls.volumes_client
+
+ @classmethod
def resource_setup(cls):
super(VolumesV2ListTestJSON, cls).resource_setup()
- cls.client = cls.volumes_client
# Create 3 test volumes
cls.volume_list = []
@@ -54,6 +58,7 @@
super(VolumesV2ListTestJSON, cls).resource_cleanup()
@test.attr(type='gate')
+ @test.idempotent_id('2a7064eb-b9c3-429b-b888-33928fc5edd3')
def test_volume_list_details_with_multiple_params(self):
# List volumes detail using combined condition
def _list_details_with_multiple_params(limit=2,
diff --git a/tempest/api_schema/response/compute/aggregates.py b/tempest/api_schema/response/compute/aggregates.py
index 9393a16..fc20885 100644
--- a/tempest/api_schema/response/compute/aggregates.py
+++ b/tempest/api_schema/response/compute/aggregates.py
@@ -14,6 +14,29 @@
import copy
+# create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
+aggregate_for_create = {
+ 'type': 'object',
+ 'properties': {
+ 'availability_zone': {'type': ['string', 'null']},
+ 'created_at': {'type': 'string'},
+ 'deleted': {'type': 'boolean'},
+ 'deleted_at': {'type': ['string', 'null']},
+ 'id': {'type': 'integer'},
+ 'name': {'type': 'string'},
+ 'updated_at': {'type': ['string', 'null']}
+ },
+ 'required': ['availability_zone', 'created_at', 'deleted',
+ 'deleted_at', 'id', 'name', 'updated_at']
+}
+
+aggregate = copy.deepcopy(aggregate_for_create)
+aggregate['properties'].update({
+ 'hosts': {'type': 'array'},
+ 'metadata': {'type': 'object'}
+})
+aggregate['required'].extend(['hosts', 'metadata'])
+
aggregate = {
'type': 'object',
'properties': {
@@ -69,18 +92,10 @@
'response_body': {
'type': 'object',
'properties': {
- 'aggregate': aggregate
+ 'aggregate': aggregate_for_create
},
'required': ['aggregate']
}
}
-# create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
-del common_create_aggregate['response_body']['properties']['aggregate'][
- 'properties']['hosts']
-del common_create_aggregate['response_body']['properties']['aggregate'][
- 'properties']['metadata']
-common_create_aggregate['response_body']['properties']['aggregate'][
- 'required'] = ['availability_zone', 'created_at', 'deleted', 'deleted_at',
- 'id', 'name', 'updated_at']
aggregate_add_remove_host = get_aggregate
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/baremetal_nodes.py
new file mode 100644
index 0000000..e82792c
--- /dev/null
+++ b/tempest/api_schema/response/compute/baremetal_nodes.py
@@ -0,0 +1,53 @@
+# 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.
+
+node = {
+ 'type': 'object',
+ 'properties': {
+ 'id': {'type': 'string'},
+ 'interfaces': {'type': 'array'},
+ 'host': {'type': 'string'},
+ 'task_state': {'type': ['string', 'null']},
+ 'cpus': {'type': ['integer', 'string']},
+ 'memory_mb': {'type': ['integer', 'string']},
+ 'disk_gb': {'type': ['integer', 'string']},
+ },
+ 'required': ['id', 'interfaces', 'host', 'task_state', 'cpus', 'memory_mb',
+ 'disk_gb']
+}
+
+list_baremetal_nodes = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'nodes': {
+ 'type': 'array',
+ 'items': node
+ }
+ },
+ 'required': ['nodes']
+ }
+}
+
+get_baremetal_node = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'node': node
+ },
+ 'required': ['node']
+ }
+}
diff --git a/tempest/api_schema/response/compute/flavors.py b/tempest/api_schema/response/compute/flavors.py
index 44020d2..65f2c28 100644
--- a/tempest/api_schema/response/compute/flavors.py
+++ b/tempest/api_schema/response/compute/flavors.py
@@ -30,8 +30,11 @@
},
'required': ['name', 'links', 'id']
}
- }
+ },
+ 'flavors_links': parameter_types.links
},
+ # NOTE(gmann): flavors_links attribute is not necessary
+ # to be present always So it is not 'required'.
'required': ['flavors']
}
}
diff --git a/tempest/api_schema/response/compute/hypervisors.py b/tempest/api_schema/response/compute/hypervisors.py
index e9e1bc9..273b579 100644
--- a/tempest/api_schema/response/compute/hypervisors.py
+++ b/tempest/api_schema/response/compute/hypervisors.py
@@ -160,9 +160,14 @@
'items': {
'type': 'object',
'properties': {
+ 'status': {'type': 'string'},
+ 'state': {'type': 'string'},
'id': {'type': ['integer', 'string']},
'hypervisor_hostname': {'type': 'string'}
},
+ # NOTE: When loading os-hypervisor-status extension,
+ # a response contains status and state. So these params
+ # should not be required.
'required': ['id', 'hypervisor_hostname']
}
}
diff --git a/tempest/api_schema/response/compute/quotas.py b/tempest/api_schema/response/compute/quotas.py
index f49771e..863104c 100644
--- a/tempest/api_schema/response/compute/quotas.py
+++ b/tempest/api_schema/response/compute/quotas.py
@@ -28,8 +28,13 @@
'metadata_items': {'type': 'integer'},
'key_pairs': {'type': 'integer'},
'security_groups': {'type': 'integer'},
- 'security_group_rules': {'type': 'integer'}
+ 'security_group_rules': {'type': 'integer'},
+ 'server_group_members': {'type': 'integer'},
+ 'server_groups': {'type': 'integer'},
},
+ # NOTE: server_group_members and server_groups are represented
+ # when enabling quota_server_group extension. So they should
+ # not be required.
'required': ['instances', 'cores', 'ram',
'floating_ips', 'fixed_ips',
'metadata_items', 'key_pairs',
diff --git a/tempest/api_schema/response/compute/v2/flavors.py b/tempest/api_schema/response/compute/v2/flavors.py
index 811ea84..76c4cee 100644
--- a/tempest/api_schema/response/compute/v2/flavors.py
+++ b/tempest/api_schema/response/compute/v2/flavors.py
@@ -15,6 +15,7 @@
import copy
from tempest.api_schema.response.compute import flavors
+from tempest.api_schema.response.compute import parameter_types
list_flavors_details = copy.deepcopy(flavors.common_flavor_list_details)
@@ -23,6 +24,12 @@
list_flavors_details['response_body']['properties']['flavors']['items'][
'properties']['swap'] = {'type': ['string', 'integer']}
+# Defining 'flavors_links' attributes for V2 flavor schema
+list_flavors_details['response_body'][
+ 'properties'].update({'flavors_links': parameter_types.links})
+# NOTE(gmann): flavors_links attribute is not necessary to be
+# present always So it is not 'required'.
+
# Defining extra attributes for V2 flavor schema
list_flavors_details['response_body']['properties']['flavors']['items'][
'properties'].update({'OS-FLV-DISABLED:disabled': {'type': 'boolean'},
diff --git a/tempest/api_schema/response/compute/v2/floating_ips.py b/tempest/api_schema/response/compute/v2/floating_ips.py
index def0a78..7250773 100644
--- a/tempest/api_schema/response/compute/v2/floating_ips.py
+++ b/tempest/api_schema/response/compute/v2/floating_ips.py
@@ -146,8 +146,14 @@
'instance_uuid': {'type': ['string', 'null']},
'interface': {'type': ['string', 'null']},
'pool': {'type': ['string', 'null']},
- 'project_id': {'type': ['string', 'null']}
+ 'project_id': {'type': ['string', 'null']},
+ 'fixed_ip': {
+ 'type': ['string', 'null'],
+ 'format': 'ip-address'
+ }
},
+ # NOTE: fixed_ip is introduced after JUNO release,
+ # So it is not defined as 'required'.
'required': ['address', 'instance_uuid', 'interface',
'pool', 'project_id']
}
diff --git a/tempest/api_schema/response/compute/v2/images.py b/tempest/api_schema/response/compute/v2/images.py
index 923c744..2317e6b 100644
--- a/tempest/api_schema/response/compute/v2/images.py
+++ b/tempest/api_schema/response/compute/v2/images.py
@@ -12,15 +12,20 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
from tempest.api_schema.response.compute import parameter_types
+image_links = copy.deepcopy(parameter_types.links)
+image_links['items']['properties'].update({'type': {'type': 'string'}})
+
common_image_schema = {
'type': 'object',
'properties': {
'id': {'type': 'string'},
'status': {'type': 'string'},
'updated': {'type': 'string'},
- 'links': parameter_types.links,
+ 'links': image_links,
'name': {'type': 'string'},
'created': {'type': 'string'},
'minDisk': {'type': 'integer'},
@@ -67,7 +72,7 @@
'type': 'object',
'properties': {
'id': {'type': 'string'},
- 'links': parameter_types.links,
+ 'links': image_links,
'name': {'type': 'string'}
},
'required': ['id', 'links', 'name']
diff --git a/tempest/api_schema/response/compute/v2/limits.py b/tempest/api_schema/response/compute/v2/limits.py
index b9857f1..a7decb7 100644
--- a/tempest/api_schema/response/compute/v2/limits.py
+++ b/tempest/api_schema/response/compute/v2/limits.py
@@ -38,8 +38,15 @@
'maxSecurityGroupRules': {'type': 'integer'},
'maxTotalKeypairs': {'type': 'integer'},
'totalRAMUsed': {'type': 'integer'},
- 'totalInstancesUsed': {'type': 'integer'}
+ 'totalInstancesUsed': {'type': 'integer'},
+ 'maxServerGroupMembers': {'type': 'integer'},
+ 'maxServerGroups': {'type': 'integer'},
+ 'totalServerGroupsUsed': {'type': 'integer'}
},
+ # NOTE(gmann): maxServerGroupMembers, maxServerGroups
+ # and totalServerGroupsUsed are API extension,
+ # and some environments return a response without these
+ # attributes.So they are not 'required'.
'required': ['maxImageMeta',
'maxPersonality',
'maxPersonalitySize',
diff --git a/tempest/api_schema/response/compute/v2/servers.py b/tempest/api_schema/response/compute/v2/servers.py
index 09abaed..0132350 100644
--- a/tempest/api_schema/response/compute/v2/servers.py
+++ b/tempest/api_schema/response/compute/v2/servers.py
@@ -30,10 +30,10 @@
'links': parameter_types.links,
'OS-DCF:diskConfig': {'type': 'string'}
},
- # NOTE: OS-DCF:diskConfig is API extension, and some
- # environments return a response without the attribute.
- # So it is not 'required'.
- 'required': ['id', 'security_groups', 'links']
+ # NOTE: OS-DCF:diskConfig & security_groups are API extension,
+ # and some environments return a response without these
+ # attributes.So they are not 'required'.
+ 'required': ['id', 'links']
}
},
'required': ['server']
@@ -64,6 +64,7 @@
get_server['response_body']['properties']['server']['properties'].update({
'key_name': {'type': ['string', 'null']},
'hostId': {'type': 'string'},
+ 'security_groups': {'type': 'array'},
# NOTE: Non-admin users also can see "OS-SRV-USG" and "OS-EXT-AZ"
# attributes.
@@ -288,10 +289,11 @@
'properties'].update({
'hostId': {'type': 'string'},
'OS-DCF:diskConfig': {'type': 'string'},
+ 'security_groups': {'type': 'array'},
'accessIPv4': parameter_types.access_ip_v4,
'accessIPv6': parameter_types.access_ip_v6
})
-# NOTE(GMann): OS-DCF:diskConfig and accessIPv4/v6 are API
+# NOTE(GMann): OS-DCF:diskConfig, security_groups and accessIPv4/v6 are API
# extensions, and some environments return a response
# without these attributes. So they are not 'required'.
list_servers_detail['response_body']['properties']['servers']['items'][
diff --git a/tempest/auth.py b/tempest/auth.py
index 6a92b5f..9d8341c 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -22,13 +22,11 @@
import six
-from tempest import config
from tempest.openstack.common import log as logging
-from tempest.services.identity.json import token_client as json_id
+from tempest.services.identity.v2.json import token_client as json_v2id
from tempest.services.identity.v3.json import token_client as json_v3id
-CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -38,34 +36,21 @@
Provide authentication
"""
- def __init__(self, credentials, interface=None):
+ def __init__(self, credentials):
"""
:param credentials: credentials for authentication
- :param interface: 'json' or 'xml'. Applicable for tempest client only
- (deprecated: only json now supported)
"""
- credentials = self._convert_credentials(credentials)
if self.check_credentials(credentials):
self.credentials = credentials
else:
raise TypeError("Invalid credentials")
- self.interface = 'json'
self.cache = None
self.alt_auth_data = None
self.alt_part = None
- def _convert_credentials(self, credentials):
- # Support dict credentials for backwards compatibility
- if isinstance(credentials, dict):
- return get_credentials(**credentials)
- else:
- return credentials
-
def __str__(self):
- return "Creds :{creds}, interface: {interface}, " \
- "cached auth data: {cache}".format(
- creds=self.credentials, interface=self.interface,
- cache=self.cache)
+ return "Creds :{creds}, cached auth data: {cache}".format(
+ creds=self.credentials, cache=self.cache)
@abc.abstractmethod
def _decorate_request(self, filters, method, url, headers=None, body=None,
@@ -201,9 +186,14 @@
token_expiry_threshold = datetime.timedelta(seconds=60)
- def __init__(self, credentials, interface=None):
- super(KeystoneAuthProvider, self).__init__(credentials, interface)
- self.auth_client = self._auth_client()
+ def __init__(self, credentials, auth_url,
+ disable_ssl_certificate_validation=None,
+ ca_certs=None, trace_requests=None):
+ super(KeystoneAuthProvider, self).__init__(credentials)
+ self.dsvm = disable_ssl_certificate_validation
+ self.ca_certs = ca_certs
+ self.trace_requests = trace_requests
+ self.auth_client = self._auth_client(auth_url)
def _decorate_request(self, filters, method, url, headers=None, body=None,
auth_data=None):
@@ -251,8 +241,10 @@
EXPIRY_DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
- def _auth_client(self):
- return json_id.TokenClientJSON()
+ def _auth_client(self, auth_url):
+ return json_v2id.TokenClientJSON(
+ auth_url, disable_ssl_certificate_validation=self.dsvm,
+ ca_certs=self.ca_certs, trace_requests=self.trace_requests)
def _auth_params(self):
return dict(
@@ -329,15 +321,18 @@
EXPIRY_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
- def _auth_client(self):
- return json_v3id.V3TokenClientJSON()
+ def _auth_client(self, auth_url):
+ return json_v3id.V3TokenClientJSON(
+ auth_url, disable_ssl_certificate_validation=self.dsvm,
+ ca_certs=self.ca_certs, trace_requests=self.trace_requests)
def _auth_params(self):
return dict(
user=self.credentials.username,
password=self.credentials.password,
- tenant=self.credentials.tenant_name,
- domain=self.credentials.user_domain_name,
+ project=self.credentials.tenant_name,
+ user_domain=self.credentials.user_domain_name,
+ project_domain=self.credentials.project_domain_name,
auth_data=True)
def _fill_credentials(self, auth_data_body):
@@ -440,47 +435,43 @@
datetime.datetime.utcnow()
-def get_default_credentials(credential_type, fill_in=True):
- """
- Returns configured credentials of the specified type
- based on the configured auth_version
- """
- return get_credentials(fill_in=fill_in, credential_type=credential_type)
+def is_identity_version_supported(identity_version):
+ return identity_version in IDENTITY_VERSION
-def get_credentials(credential_type=None, fill_in=True, **kwargs):
+def get_credentials(auth_url, fill_in=True, identity_version='v2', **kwargs):
"""
Builds a credentials object based on the configured auth_version
- :param credential_type (string): requests credentials from tempest
- configuration file. Valid values are defined in
- Credentials.TYPE.
- :param kwargs (dict): take into account only if credential_type is
- not specified or None. Dict of credential key/value pairs
+ :param auth_url (string): Full URI of the OpenStack Identity API(Keystone)
+ which is used to fetch the token from Identity service.
+ :param fill_in (boolean): obtain a token and fill in all credential
+ details provided by the identity service. When fill_in is not
+ specified, credentials are not validated. Validation can be invoked
+ by invoking ``is_valid()``
+ :param identity_version (string): identity API version is used to
+ select the matching auth provider and credentials class
+ :param kwargs (dict): Dict of credential key/value pairs
Examples:
Returns credentials from the provided parameters:
>>> get_credentials(username='foo', password='bar')
- Returns credentials from tempest configuration:
- >>> get_credentials(credential_type='user')
+ Returns credentials including IDs:
+ >>> get_credentials(username='foo', password='bar', fill_in=True)
"""
- if CONF.identity.auth_version == 'v2':
- credential_class = KeystoneV2Credentials
- auth_provider_class = KeystoneV2AuthProvider
- elif CONF.identity.auth_version == 'v3':
- credential_class = KeystoneV3Credentials
- auth_provider_class = KeystoneV3AuthProvider
- else:
- raise exceptions.InvalidConfiguration('Unsupported auth version')
- if credential_type is not None:
- creds = credential_class.get_default(credential_type)
- else:
- creds = credential_class(**kwargs)
+ if not is_identity_version_supported(identity_version):
+ raise exceptions.InvalidIdentityVersion(
+ identity_version=identity_version)
+
+ credential_class, auth_provider_class = IDENTITY_VERSION.get(
+ identity_version)
+
+ creds = credential_class(**kwargs)
# Fill in the credentials fields that were not specified
if fill_in:
- auth_provider = auth_provider_class(creds)
+ auth_provider = auth_provider_class(creds, auth_url)
creds = auth_provider.fill_credentials()
return creds
@@ -490,18 +481,9 @@
Set of credentials for accessing OpenStack services
ATTRIBUTES: list of valid class attributes representing credentials.
-
- TYPES: types of credentials available in the configuration file.
- For each key there's a tuple (section, prefix) to match the
- configuration options.
"""
ATTRIBUTES = []
- TYPES = {
- 'identity_admin': ('identity', 'admin'),
- 'user': ('identity', None),
- 'alt_user': ('identity', 'alt')
- }
def __init__(self, **kwargs):
"""
@@ -554,21 +536,8 @@
except AttributeError:
return default
- @classmethod
- def get_default(cls, credentials_type):
- if credentials_type not in cls.TYPES:
- raise exceptions.InvalidCredentials()
- creds = cls._get_default(credentials_type)
- if not creds.is_valid():
- msg = ("The %s credentials are incorrectly set in the config file."
- " Double check that all required values are assigned" %
- credentials_type)
- raise exceptions.InvalidConfiguration(msg)
- return creds
-
- @classmethod
- def _get_default(cls, credentials_type):
- raise NotImplementedError
+ def get_init_attributes(self):
+ return self._initial.keys()
def is_valid(self):
raise NotImplementedError
@@ -584,21 +553,8 @@
class KeystoneV2Credentials(Credentials):
- CONF_ATTRIBUTES = ['username', 'password', 'tenant_name']
- ATTRIBUTES = ['user_id', 'tenant_id']
- ATTRIBUTES.extend(CONF_ATTRIBUTES)
-
- @classmethod
- def _get_default(cls, credentials_type='user'):
- params = {}
- section, prefix = cls.TYPES[credentials_type]
- for attr in cls.CONF_ATTRIBUTES:
- _section = getattr(CONF, section)
- if prefix is None:
- params[attr] = getattr(_section, attr)
- else:
- params[attr] = getattr(_section, prefix + "_" + attr)
- return cls(**params)
+ ATTRIBUTES = ['username', 'password', 'tenant_name', 'user_id',
+ 'tenant_id']
def is_valid(self):
"""
@@ -608,26 +564,15 @@
return None not in (self.username, self.password)
-class KeystoneV3Credentials(KeystoneV2Credentials):
+class KeystoneV3Credentials(Credentials):
"""
Credentials suitable for the Keystone Identity V3 API
"""
- CONF_ATTRIBUTES = ['domain_name', 'password', 'tenant_name', 'username']
- ATTRIBUTES = ['project_domain_id', 'project_domain_name', 'project_id',
+ ATTRIBUTES = ['domain_name', 'password', 'tenant_name', 'username',
+ 'project_domain_id', 'project_domain_name', 'project_id',
'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
'user_domain_name', 'user_id']
- ATTRIBUTES.extend(CONF_ATTRIBUTES)
-
- def __init__(self, **kwargs):
- """
- If domain is not specified, load the one configured for the
- identity manager.
- """
- domain_fields = set(x for x in self.ATTRIBUTES if 'domain' in x)
- if not domain_fields.intersection(kwargs.keys()):
- kwargs['user_domain_name'] = CONF.identity.admin_domain_name
- super(KeystoneV3Credentials, self).__init__(**kwargs)
def __setattr__(self, key, value):
parent = super(KeystoneV3Credentials, self)
@@ -685,3 +630,7 @@
self.project_id is not None,
self.project_name is not None and valid_project_domain])
return all([self.password is not None, valid_user, valid_project])
+
+
+IDENTITY_VERSION = {'v2': (KeystoneV2Credentials, KeystoneV2AuthProvider),
+ 'v3': (KeystoneV3Credentials, KeystoneV3AuthProvider)}
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 4782129..6733204 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -68,14 +68,22 @@
class ClientTestBase(test.BaseTestCase):
+
+ @classmethod
+ def skip_checks(cls):
+ super(ClientTestBase, cls).skip_checks()
+ if not CONF.identity_feature_enabled.api_v2:
+ raise cls.skipException("CLI clients rely on identity v2 API, "
+ "which is configured as not available")
+
@classmethod
def resource_setup(cls):
if not CONF.cli.enabled:
msg = "cli testing disabled"
raise cls.skipException(msg)
super(ClientTestBase, cls).resource_setup()
- cls.cred_prov = credentials.get_isolated_credentials(cls.__name__)
- cls.creds = cls.cred_prov.get_admin_creds()
+ cls.isolated_creds = credentials.get_isolated_credentials(cls.__name__)
+ cls.creds = cls.isolated_creds.get_admin_creds()
def _get_clients(self):
clients = base.CLIClient(self.creds.username,
diff --git a/tempest/cli/simple_read_only/compute/__init__.py b/tempest/cli/simple_read_only/compute/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/compute/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/compute/test_nova.py b/tempest/cli/simple_read_only/compute/test_nova.py
deleted file mode 100644
index aee92fa..0000000
--- a/tempest/cli/simple_read_only/compute/test_nova.py
+++ /dev/null
@@ -1,209 +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_lib import decorators
-from tempest_lib import exceptions
-import testtools
-
-from tempest import cli
-from tempest import config
-from tempest.openstack.common import log as logging
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlyNovaClientTest(cli.ClientTestBase):
-
- """
- This is a first pass at a simple read only python-novaclient test. This
- only exercises client commands that are read only.
-
- This should test commands:
- * as a regular user
- * as a admin user
- * with and without optional parameters
- * initially just check return codes, and later test command outputs
-
- """
-
- @classmethod
- def resource_setup(cls):
- if not CONF.service_available.nova:
- msg = ("%s skipped as Nova is not available" % cls.__name__)
- raise cls.skipException(msg)
- super(SimpleReadOnlyNovaClientTest, cls).resource_setup()
-
- def nova(self, *args, **kwargs):
- return self.clients.nova(*args,
- endpoint_type=CONF.compute.endpoint_type,
- **kwargs)
-
- def test_admin_fake_action(self):
- self.assertRaises(exceptions.CommandFailed,
- self.nova,
- 'this-does-nova-exist')
-
- # NOTE(jogo): Commands in order listed in 'nova help'
-
- # Positional arguments:
-
- def test_admin_absolute_limites(self):
- self.nova('absolute-limits')
- self.nova('absolute-limits', params='--reserved')
-
- def test_admin_aggregate_list(self):
- self.nova('aggregate-list')
-
- def test_admin_availability_zone_list(self):
- self.assertIn("internal", self.nova('availability-zone-list'))
-
- def test_admin_cloudpipe_list(self):
- self.nova('cloudpipe-list')
-
- def test_admin_credentials(self):
- self.nova('credentials')
-
- @testtools.skipIf(CONF.service_available.neutron,
- "Neutron does not provide this feature")
- def test_admin_dns_domains(self):
- self.nova('dns-domains')
-
- @decorators.skip_because(bug="1157349")
- def test_admin_dns_list(self):
- self.nova('dns-list')
-
- def test_admin_endpoints(self):
- self.nova('endpoints')
-
- def test_admin_flavor_acces_list(self):
- self.assertRaises(exceptions.CommandFailed,
- self.nova,
- 'flavor-access-list')
- # Failed to get access list for public flavor type
- self.assertRaises(exceptions.CommandFailed,
- self.nova,
- 'flavor-access-list',
- params='--flavor m1.tiny')
-
- def test_admin_flavor_list(self):
- self.assertIn("Memory_MB", self.nova('flavor-list'))
-
- def test_admin_floating_ip_bulk_list(self):
- self.nova('floating-ip-bulk-list')
-
- def test_admin_floating_ip_list(self):
- self.nova('floating-ip-list')
-
- def test_admin_floating_ip_pool_list(self):
- self.nova('floating-ip-pool-list')
-
- def test_admin_host_list(self):
- self.nova('host-list')
-
- def test_admin_hypervisor_list(self):
- self.nova('hypervisor-list')
-
- def test_admin_image_list(self):
- self.nova('image-list')
-
- @decorators.skip_because(bug="1157349")
- def test_admin_interface_list(self):
- self.nova('interface-list')
-
- def test_admin_keypair_list(self):
- self.nova('keypair-list')
-
- def test_admin_list(self):
- self.nova('list')
- self.nova('list', params='--all-tenants 1')
- self.nova('list', params='--all-tenants 0')
- self.assertRaises(exceptions.CommandFailed,
- self.nova,
- 'list',
- params='--all-tenants bad')
-
- def test_admin_network_list(self):
- self.nova('network-list')
-
- def test_admin_rate_limits(self):
- self.nova('rate-limits')
-
- def test_admin_secgroup_list(self):
- self.nova('secgroup-list')
-
- @decorators.skip_because(bug="1157349")
- def test_admin_secgroup_list_rules(self):
- self.nova('secgroup-list-rules')
-
- @cli.min_client_version(client='nova', version='2.18')
- def test_admin_server_group_list(self):
- self.nova('server-group-list')
-
- def test_admin_servce_list(self):
- self.nova('service-list')
-
- def test_admin_usage(self):
- self.nova('usage')
-
- def test_admin_usage_list(self):
- self.nova('usage-list')
-
- @testtools.skipIf(not CONF.service_available.cinder,
- "Skipped as Cinder is not available")
- def test_admin_volume_list(self):
- self.nova('volume-list')
-
- @testtools.skipIf(not CONF.service_available.cinder,
- "Skipped as Cinder is not available")
- def test_admin_volume_snapshot_list(self):
- self.nova('volume-snapshot-list')
-
- @testtools.skipIf(not CONF.service_available.cinder,
- "Skipped as Cinder is not available")
- def test_admin_volume_type_list(self):
- self.nova('volume-type-list')
-
- def test_admin_help(self):
- self.nova('help')
-
- def test_admin_list_extensions(self):
- self.nova('list-extensions')
-
- def test_admin_net_list(self):
- self.nova('net-list')
-
- def test_agent_list(self):
- self.nova('agent-list')
- self.nova('agent-list', flags='--debug')
-
- def test_migration_list(self):
- self.nova('migration-list')
- self.nova('migration-list', flags='--debug')
-
- # Optional arguments:
-
- def test_admin_version(self):
- self.nova('', flags='--version')
-
- def test_admin_debug_list(self):
- self.nova('list', flags='--debug')
-
- def test_admin_timeout(self):
- self.nova('list', flags='--timeout %d' % CONF.cli.timeout)
-
- def test_admin_timing(self):
- self.nova('list', flags='--timing')
diff --git a/tempest/cli/simple_read_only/data_processing/test_sahara.py b/tempest/cli/simple_read_only/data_processing/test_sahara.py
index c06c2c9..153dbd2 100644
--- a/tempest/cli/simple_read_only/data_processing/test_sahara.py
+++ b/tempest/cli/simple_read_only/data_processing/test_sahara.py
@@ -47,11 +47,13 @@
*args, endpoint_type=CONF.data_processing.endpoint_type, **kwargs)
@test.attr(type='negative')
+ @test.idempotent_id('c8809259-710f-43f9-b452-54b2be3115a9')
def test_sahara_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.sahara,
'this-does-not-exist')
+ @test.idempotent_id('39afe90c-0fd8-456e-89e2-da6de9680fff')
def test_sahara_plugins_list(self):
plugins = self.parser.listing(self.sahara('plugin-list'))
self.assertTableStruct(plugins, [
@@ -60,6 +62,7 @@
'title'
])
+ @test.idempotent_id('3eb36fd8-bb06-4004-9e90-84ddf4dbcf5b')
@testtools.skipUnless(CONF.data_processing_feature_enabled.plugins,
'No plugins defined')
def test_sahara_plugins_show(self):
@@ -72,6 +75,7 @@
'Value'
])
+ @test.idempotent_id('502b684b-3d41-4619-aa6c-4db3465ae79d')
def test_sahara_node_group_template_list(self):
result = self.sahara('node-group-template-list')
node_group_templates = self.parser.listing(result)
@@ -83,6 +87,7 @@
'description'
])
+ @test.idempotent_id('6c36fe4d-3b88-4b0d-b702-2a051db7dae7')
def test_sahara_cluster_template_list(self):
result = self.sahara('cluster-template-list')
cluster_templates = self.parser.listing(result)
@@ -94,6 +99,7 @@
'description'
])
+ @test.idempotent_id('b951949d-b9a6-49db-add5-8a18ac533810')
def test_sahara_cluster_list(self):
result = self.sahara('cluster-list')
clusters = self.parser.listing(result)
@@ -104,6 +110,7 @@
'node_count'
])
+ @test.idempotent_id('dbc83a8c-15b6-4aa8-b274-5896577397e1')
def test_sahara_data_source_list(self):
result = self.sahara('data-source-list')
data_sources = self.parser.listing(result)
@@ -114,6 +121,7 @@
'description'
])
+ @test.idempotent_id('a8f77e05-d4bf-45c3-8245-57835d0de37b')
def test_sahara_job_binary_data_list(self):
result = self.sahara('job-binary-data-list')
job_binary_data_list = self.parser.listing(result)
@@ -122,6 +130,7 @@
'name'
])
+ @test.idempotent_id('a8f4d0f3-fa1c-49ce-b73f-d624d89dc381')
def test_sahara_job_binary_list(self):
result = self.sahara('job-binary-list')
job_binaries = self.parser.listing(result)
@@ -131,6 +140,7 @@
'description'
])
+ @test.idempotent_id('91164ca4-d049-49e0-a52a-686b408196ff')
def test_sahara_job_template_list(self):
result = self.sahara('job-template-list')
job_templates = self.parser.listing(result)
@@ -140,6 +150,7 @@
'description'
])
+ @test.idempotent_id('6829c251-a8b6-449d-af86-7dd98b69a7ce')
def test_sahara_job_list(self):
result = self.sahara('job-list')
jobs = self.parser.listing(result)
@@ -149,10 +160,12 @@
'status'
])
+ @test.idempotent_id('e4bd5d3b-474b-4b7a-82ab-f6bb0bc89faf')
def test_sahara_bash_completion(self):
self.sahara('bash-completion')
# Optional arguments
+ @test.idempotent_id('699c14e5-632e-46b8-91e5-6bff8c8307e5')
def test_sahara_help(self):
help_text = self.sahara('help')
lines = help_text.split('\n')
@@ -172,6 +185,7 @@
'plugin-list', 'job-binary-create', 'help'))
self.assertFalse(wanted_commands - commands)
+ @test.idempotent_id('84a18ea6-6379-4024-af6b-0e938f60dfc2')
def test_sahara_version(self):
version = self.sahara('', flags='--version')
self.assertTrue(re.search('[0-9.]+', version))
diff --git a/tempest/cli/simple_read_only/identity/test_keystone.py b/tempest/cli/simple_read_only/identity/test_keystone.py
index 1fc7908..10a26d5 100644
--- a/tempest/cli/simple_read_only/identity/test_keystone.py
+++ b/tempest/cli/simple_read_only/identity/test_keystone.py
@@ -20,6 +20,7 @@
from tempest import cli
from tempest import config
from tempest.openstack.common import log as logging
+from tempest import test
CONF = config.CONF
@@ -38,11 +39,13 @@
def keystone(self, *args, **kwargs):
return self.clients.keystone(*args, **kwargs)
+ @test.idempotent_id('19c3ae95-3c19-4bba-8ba3-48ad19939b71')
def test_admin_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.keystone,
'this-does-not-exist')
+ @test.idempotent_id('a1100917-c7c5-4887-a4da-f7d7f13194f5')
def test_admin_catalog_list(self):
out = self.keystone('catalog')
catalog = self.parser.details_multiple(out, with_label=True)
@@ -57,6 +60,7 @@
self.assertIn('publicURL', svc.keys())
self.assertIn('region', svc.keys())
+ @test.idempotent_id('35c73506-eab6-4abc-956e-42da90aba8ec')
def test_admin_endpoint_list(self):
out = self.keystone('endpoint-list')
endpoints = self.parser.listing(out)
@@ -64,6 +68,7 @@
'id', 'region', 'publicurl', 'internalurl',
'adminurl', 'service_id'])
+ @test.idempotent_id('f17cb155-bd16-4f32-9956-1b073752fc07')
def test_admin_endpoint_service_match(self):
endpoints = self.parser.listing(self.keystone('endpoint-list'))
services = self.parser.listing(self.keystone('service-list'))
@@ -73,33 +78,40 @@
for endpoint in endpoints:
self.assertIn(endpoint['service_id'], svc_by_id)
+ @test.idempotent_id('be7176f2-9c34-4d84-bb7d-b4bc85d06a33')
def test_admin_role_list(self):
roles = self.parser.listing(self.keystone('role-list'))
self.assertTableStruct(roles, ['id', 'name'])
+ @test.idempotent_id('96a4de8d-aa9e-4ca5-89f0-985809eccd66')
def test_admin_service_list(self):
services = self.parser.listing(self.keystone('service-list'))
self.assertTableStruct(services, ['id', 'name', 'type', 'description'])
+ @test.idempotent_id('edb45480-0f7b-49eb-8f95-7562cbba96da')
def test_admin_tenant_list(self):
tenants = self.parser.listing(self.keystone('tenant-list'))
self.assertTableStruct(tenants, ['id', 'name', 'enabled'])
+ @test.idempotent_id('25a2753d-6bd1-40c0-addc-32864b00cb2d')
def test_admin_user_list(self):
users = self.parser.listing(self.keystone('user-list'))
self.assertTableStruct(users, [
'id', 'name', 'enabled', 'email'])
+ @test.idempotent_id('f92bf8d4-b27b-47c9-8450-e27c57758de9')
def test_admin_user_role_list(self):
user_roles = self.parser.listing(self.keystone('user-role-list'))
self.assertTableStruct(user_roles, [
'id', 'name', 'user_id', 'tenant_id'])
+ @test.idempotent_id('14a2687b-3ce1-404c-9f78-a0e28e2f8f7b')
def test_admin_discover(self):
discovered = self.keystone('discover')
self.assertIn('Keystone found at http', discovered)
self.assertIn('supports version', discovered)
+ @test.idempotent_id('9a567c8c-3787-4e5f-9c30-bed55f2b75c0')
def test_admin_help(self):
help_text = self.keystone('help')
lines = help_text.split('\n')
@@ -118,9 +130,11 @@
'token-get', 'discover', 'bootstrap'))
self.assertFalse(wanted_commands - commands)
+ @test.idempotent_id('a7b9e1fe-db31-4846-82c5-52a7aa9863c3')
def test_admin_bashcompletion(self):
self.keystone('bash-completion')
+ @test.idempotent_id('5328c681-df8b-4874-a65c-8fa278f0af8f')
def test_admin_ec2_credentials_list(self):
creds = self.keystone('ec2-credentials-list')
creds = self.parser.listing(creds)
@@ -128,11 +142,14 @@
# Optional arguments:
+ @test.idempotent_id('af95e809-ce95-4505-8627-170d803b1d13')
def test_admin_version(self):
self.keystone('', flags='--version')
+ @test.idempotent_id('9e26521f-7bfa-4d8e-9d61-fd364f0c20c0')
def test_admin_debug_list(self):
self.keystone('catalog', flags='--debug')
+ @test.idempotent_id('097b3a52-725f-4df7-84b6-277a2b6f6e38')
def test_admin_timeout(self):
self.keystone('catalog', flags='--timeout %d' % CONF.cli.timeout)
diff --git a/tempest/cli/simple_read_only/image/test_glance.py b/tempest/cli/simple_read_only/image/test_glance.py
index 03e00d7..3d7126b 100644
--- a/tempest/cli/simple_read_only/image/test_glance.py
+++ b/tempest/cli/simple_read_only/image/test_glance.py
@@ -20,6 +20,7 @@
from tempest import cli
from tempest import config
from tempest.openstack.common import log as logging
+from tempest import test
CONF = config.CONF
@@ -46,11 +47,13 @@
endpoint_type=CONF.image.endpoint_type,
**kwargs)
+ @test.idempotent_id('c6bd9bf9-717f-4458-8d74-05b682ea7adf')
def test_glance_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.glance,
'this-does-not-exist')
+ @test.idempotent_id('72bcdaf3-11cd-48cb-bb8e-62b329acc1ef')
def test_glance_image_list(self):
out = self.glance('image-list')
endpoints = self.parser.listing(out)
@@ -58,6 +61,7 @@
'ID', 'Name', 'Disk Format', 'Container Format',
'Size', 'Status'])
+ @test.idempotent_id('965d294c-8772-4899-ba33-26ee23406135')
def test_glance_member_list(self):
tenant_name = '--tenant-id %s' % CONF.identity.admin_tenant_name
out = self.glance('member-list',
@@ -66,6 +70,7 @@
self.assertTableStruct(endpoints,
['Image ID', 'Member ID', 'Can Share'])
+ @test.idempotent_id('43b80ee5-4297-47f3-ab4c-6f81b9c6edb3')
def test_glance_help(self):
help_text = self.glance('help')
lines = help_text.split('\n')
@@ -88,11 +93,14 @@
# Optional arguments:
+ @test.idempotent_id('3b2359ea-3719-4b47-81e5-44a042572b11')
def test_glance_version(self):
self.glance('', flags='--version')
+ @test.idempotent_id('1a52d3bd-3edf-4d67-b3da-999a5d9e0c5e')
def test_glance_debug_list(self):
self.glance('image-list', flags='--debug')
+ @test.idempotent_id('6f42b076-f9a7-4e2b-a729-579f53e7814e')
def test_glance_timeout(self):
self.glance('image-list', flags='--timeout %d' % CONF.cli.timeout)
diff --git a/tempest/cli/simple_read_only/network/test_neutron.py b/tempest/cli/simple_read_only/network/test_neutron.py
index 6cf0640..8af8ada 100644
--- a/tempest/cli/simple_read_only/network/test_neutron.py
+++ b/tempest/cli/simple_read_only/network/test_neutron.py
@@ -48,28 +48,33 @@
**kwargs)
@test.attr(type='smoke')
+ @test.idempotent_id('84dd7190-2b98-4709-8e2c-3c1d25b9e7d2')
def test_neutron_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.neutron,
'this-does-not-exist')
@test.attr(type='smoke')
+ @test.idempotent_id('c598c337-313a-45ac-bf27-d6b4124a9e5b')
def test_neutron_net_list(self):
net_list = self.parser.listing(self.neutron('net-list'))
self.assertTableStruct(net_list, ['id', 'name', 'subnets'])
@test.attr(type='smoke')
+ @test.idempotent_id('3e172b04-2e3b-4fcf-922d-99d5c803779f')
def test_neutron_ext_list(self):
ext = self.parser.listing(self.neutron('ext-list'))
self.assertTableStruct(ext, ['alias', 'name'])
@test.attr(type='smoke')
+ @test.idempotent_id('2e0de814-52d6-4f81-be17-fe327072fc23')
@test.requires_ext(extension='dhcp_agent_scheduler', service='network')
def test_neutron_dhcp_agent_list_hosting_net(self):
self.neutron('dhcp-agent-list-hosting-net',
params=CONF.compute.fixed_network_name)
@test.attr(type='smoke')
+ @test.idempotent_id('8524a24a-3895-40a5-8c9d-49d4459cdda4')
@test.requires_ext(extension='agent', service='network')
def test_neutron_agent_list(self):
agents = self.parser.listing(self.neutron('agent-list'))
@@ -77,16 +82,19 @@
self.assertTableStruct(agents, field_names)
@test.attr(type='smoke')
+ @test.idempotent_id('97c3ef92-7303-45f1-80db-b6622f176782')
@test.requires_ext(extension='router', service='network')
def test_neutron_floatingip_list(self):
self.neutron('floatingip-list')
@test.attr(type='smoke')
+ @test.idempotent_id('823e0fee-404c-49a7-8bf3-d2f0383cc649')
@test.requires_ext(extension='metering', service='network')
def test_neutron_meter_label_list(self):
self.neutron('meter-label-list')
@test.attr(type='smoke')
+ @test.idempotent_id('7fb76098-01f6-417f-b9c7-e630ba3f394b')
@test.requires_ext(extension='metering', service='network')
def test_neutron_meter_label_rule_list(self):
self.neutron('meter-label-rule-list')
@@ -100,39 +108,47 @@
self.fail('%s: Unexpected failure.' % command)
@test.attr(type='smoke')
+ @test.idempotent_id('396d1d87-fd0c-4716-9ff0-f1baa54c6c61')
def test_neutron_lb_healthmonitor_list(self):
self._test_neutron_lbaas_command('lb-healthmonitor-list')
@test.attr(type='smoke')
+ @test.idempotent_id('f41fa54d-5cd8-4f2c-bb4e-13abc72dccb6')
def test_neutron_lb_member_list(self):
self._test_neutron_lbaas_command('lb-member-list')
@test.attr(type='smoke')
+ @test.idempotent_id('3ec04885-7573-4cce-b086-5722c0b00d85')
def test_neutron_lb_pool_list(self):
self._test_neutron_lbaas_command('lb-pool-list')
@test.attr(type='smoke')
+ @test.idempotent_id('1ab530e0-ec87-498f-baf2-85f6635a2ad9')
def test_neutron_lb_vip_list(self):
self._test_neutron_lbaas_command('lb-vip-list')
@test.attr(type='smoke')
+ @test.idempotent_id('e92f7362-4009-4b37-afee-f469105b24e7')
@test.requires_ext(extension='external-net', service='network')
def test_neutron_net_external_list(self):
net_ext_list = self.parser.listing(self.neutron('net-external-list'))
self.assertTableStruct(net_ext_list, ['id', 'name', 'subnets'])
@test.attr(type='smoke')
+ @test.idempotent_id('ed840980-7c84-4b6e-b280-f13c5848a0e9')
def test_neutron_port_list(self):
port_list = self.parser.listing(self.neutron('port-list'))
self.assertTableStruct(port_list, ['id', 'name', 'mac_address',
'fixed_ips'])
@test.attr(type='smoke')
+ @test.idempotent_id('dded0dfa-f2ac-4c1f-bc90-69fd06dd7132')
@test.requires_ext(extension='quotas', service='network')
def test_neutron_quota_list(self):
self.neutron('quota-list')
@test.attr(type='smoke')
+ @test.idempotent_id('927fca1e-4397-42a2-ba47-d738299466de')
@test.requires_ext(extension='router', service='network')
def test_neutron_router_list(self):
router_list = self.parser.listing(self.neutron('router-list'))
@@ -140,12 +156,14 @@
'external_gateway_info'])
@test.attr(type='smoke')
+ @test.idempotent_id('e2e3d2d5-1aee-499d-84d9-37382dcf26ff')
@test.requires_ext(extension='security-group', service='network')
def test_neutron_security_group_list(self):
security_grp = self.parser.listing(self.neutron('security-group-list'))
self.assertTableStruct(security_grp, ['id', 'name', 'description'])
@test.attr(type='smoke')
+ @test.idempotent_id('288602c2-8b59-44cd-8c5d-1ec916a114d3')
@test.requires_ext(extension='security-group', service='network')
def test_neutron_security_group_rule_list(self):
security_grp = self.parser.listing(self.neutron
@@ -156,12 +174,14 @@
'remote_group'])
@test.attr(type='smoke')
+ @test.idempotent_id('2a874a08-b9c9-4f0f-82ef-8cadb15bbd5d')
def test_neutron_subnet_list(self):
subnet_list = self.parser.listing(self.neutron('subnet-list'))
self.assertTableStruct(subnet_list, ['id', 'name', 'cidr',
'allocation_pools'])
@test.attr(type='smoke')
+ @test.idempotent_id('048e1ec3-cf6c-4066-b262-2028e03ce825')
@test.requires_ext(extension='vpnaas', service='network')
def test_neutron_vpn_ikepolicy_list(self):
ikepolicy = self.parser.listing(self.neutron('vpn-ikepolicy-list'))
@@ -171,6 +191,7 @@
'ike_version', 'pfs'])
@test.attr(type='smoke')
+ @test.idempotent_id('bb8902b7-b2e6-49fd-b9bd-a26dd99732df')
@test.requires_ext(extension='vpnaas', service='network')
def test_neutron_vpn_ipsecpolicy_list(self):
ipsecpolicy = self.parser.listing(self.neutron('vpn-ipsecpolicy-list'))
@@ -180,6 +201,7 @@
'pfs'])
@test.attr(type='smoke')
+ @test.idempotent_id('c0f33f9a-0ba9-4177-bcd5-dce34b81d523')
@test.requires_ext(extension='vpnaas', service='network')
def test_neutron_vpn_service_list(self):
vpn_list = self.parser.listing(self.neutron('vpn-service-list'))
@@ -187,6 +209,7 @@
'router_id', 'status'])
@test.attr(type='smoke')
+ @test.idempotent_id('bb142f8a-e568-405f-b1b7-4cb458de7971')
@test.requires_ext(extension='vpnaas', service='network')
def test_neutron_ipsec_site_connection_list(self):
ipsec_site = self.parser.listing(self.neutron
@@ -198,6 +221,7 @@
'auth_mode', 'status'])
@test.attr(type='smoke')
+ @test.idempotent_id('89baff14-8cb7-4ad8-9c24-b0278711170b')
@test.requires_ext(extension='fwaas', service='network')
def test_neutron_firewall_list(self):
firewall_list = self.parser.listing(self.neutron
@@ -206,6 +230,7 @@
'firewall_policy_id'])
@test.attr(type='smoke')
+ @test.idempotent_id('996e418a-2a51-4018-9602-478ca8053e61')
@test.requires_ext(extension='fwaas', service='network')
def test_neutron_firewall_policy_list(self):
firewall_policy = self.parser.listing(self.neutron
@@ -214,6 +239,7 @@
'firewall_rules'])
@test.attr(type='smoke')
+ @test.idempotent_id('d4638dd6-98d4-4400-a920-26572de1a6fc')
@test.requires_ext(extension='fwaas', service='network')
def test_neutron_firewall_rule_list(self):
firewall_rule = self.parser.listing(self.neutron
@@ -223,6 +249,7 @@
'summary', 'enabled'])
@test.attr(type='smoke')
+ @test.idempotent_id('1c4551e1-e3f3-4af2-8a40-c3f551e4a536')
def test_neutron_help(self):
help_text = self.neutron('help')
lines = help_text.split('\n')
@@ -243,13 +270,16 @@
# Optional arguments:
@test.attr(type='smoke')
+ @test.idempotent_id('381e6fe3-cddc-47c9-a773-70ddb2f79a91')
def test_neutron_version(self):
self.neutron('', flags='--version')
@test.attr(type='smoke')
+ @test.idempotent_id('bcad0e07-da8c-4c7c-8ab6-499e5d7ab8cb')
def test_neutron_debug_net_list(self):
self.neutron('net-list', flags='--debug')
@test.attr(type='smoke')
+ @test.idempotent_id('3e42d78e-65e5-4e8f-8c29-ca7be8feebb4')
def test_neutron_quiet_net_list(self):
self.neutron('net-list', flags='--quiet')
diff --git a/tempest/cli/simple_read_only/object_storage/test_swift.py b/tempest/cli/simple_read_only/object_storage/test_swift.py
index 40c4c15..7201eab 100644
--- a/tempest/cli/simple_read_only/object_storage/test_swift.py
+++ b/tempest/cli/simple_read_only/object_storage/test_swift.py
@@ -19,6 +19,7 @@
from tempest import cli
from tempest import config
+from tempest import test
CONF = config.CONF
@@ -42,14 +43,17 @@
return self.clients.swift(
*args, endpoint_type=CONF.object_storage.endpoint_type, **kwargs)
+ @test.idempotent_id('74360cdc-e7ec-493f-8a87-2b65f4d54aa3')
def test_swift_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.swift,
'this-does-not-exist')
+ @test.idempotent_id('809ec373-828e-4279-8df6-9d4db81c7909')
def test_swift_list(self):
self.swift('list')
+ @test.idempotent_id('325d5fe4-e5ab-4f52-aec4-357533f24fa1')
def test_swift_stat(self):
output = self.swift('stat')
entries = ['Account', 'Containers', 'Objects', 'Bytes', 'Content-Type',
@@ -57,6 +61,7 @@
for entry in entries:
self.assertTrue(entry in output)
+ @test.idempotent_id('af1483e1-dafd-4552-a39b-b9d337df808b')
def test_swift_capabilities(self):
output = self.swift('capabilities')
entries = ['account_listing_limit', 'container_listing_limit',
@@ -64,6 +69,7 @@
for entry in entries:
self.assertTrue(entry in output)
+ @test.idempotent_id('29c83a64-8eb7-418c-a39b-c70cefa5b695')
def test_swift_help(self):
help_text = self.swift('', flags='--help')
lines = help_text.split('\n')
@@ -84,15 +90,19 @@
# Optional arguments:
+ @test.idempotent_id('2026be82-4e53-4414-a828-f1c894b8cf0f')
def test_swift_version(self):
self.swift('', flags='--version')
+ @test.idempotent_id('0ae6172e-3df7-42b8-a987-d42609ada6ed')
def test_swift_debug_list(self):
self.swift('list', flags='--debug')
+ @test.idempotent_id('1bdf5dd0-7df5-446c-a124-2b0703a5d199')
def test_swift_retries_list(self):
self.swift('list', flags='--retries 3')
+ @test.idempotent_id('64eae749-8fbd-4d85-bc7f-f706d3581c6f')
def test_swift_region_list(self):
region = CONF.object_storage.region
if not region:
diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py
index d3a9b01..7751e2c 100644
--- a/tempest/cli/simple_read_only/orchestration/test_heat.py
+++ b/tempest/cli/simple_read_only/orchestration/test_heat.py
@@ -18,6 +18,7 @@
import tempest.cli
from tempest import config
from tempest.openstack.common import log as logging
+from tempest import test
CONF = config.CONF
@@ -46,58 +47,71 @@
return self.clients.heat(
*args, endpoint_type=CONF.orchestration.endpoint_type, **kwargs)
+ @test.idempotent_id('0ae034bb-ce35-45e8-b7aa-3e339cd3140f')
def test_heat_stack_list(self):
self.heat('stack-list')
+ @test.idempotent_id('a360d069-7250-4aed-9721-0a6f2db7c3fa')
def test_heat_stack_list_debug(self):
self.heat('stack-list', flags='--debug')
+ @test.idempotent_id('e1b7c177-5ab4-4d3f-8a26-ea01ebbd2b8c')
def test_heat_resource_template_fmt_default(self):
ret = self.heat('resource-template OS::Nova::Server')
self.assertIn('Type: OS::Nova::Server', ret)
+ @test.idempotent_id('93f82f76-aab2-4910-9359-11cf48f2a46b')
def test_heat_resource_template_fmt_arg_short_yaml(self):
ret = self.heat('resource-template -F yaml OS::Nova::Server')
self.assertIn('Type: OS::Nova::Server', ret)
self.assertIsInstance(yaml.safe_load(ret), dict)
+ @test.idempotent_id('7356a98c-e14d-43f0-8c25-c9f7daa0aafa')
def test_heat_resource_template_fmt_arg_long_json(self):
ret = self.heat('resource-template --format json OS::Nova::Server')
self.assertIn('"Type": "OS::Nova::Server"', ret)
self.assertIsInstance(json.loads(ret), dict)
+ @test.idempotent_id('2fd99d20-beff-4667-b42e-de9095f671d7')
def test_heat_resource_type_list(self):
ret = self.heat('resource-type-list')
rsrc_types = self.parser.listing(ret)
self.assertTableStruct(rsrc_types, ['resource_type'])
+ @test.idempotent_id('62f60dbf-d139-4698-b230-a09fb531d643')
def test_heat_resource_type_show(self):
rsrc_schema = self.heat('resource-type-show OS::Nova::Server')
# resource-type-show returns a json resource schema
self.assertIsInstance(json.loads(rsrc_schema), dict)
+ @test.idempotent_id('6ca16ff7-9d5f-4448-a8c2-4cecc7b5ba3a')
def test_heat_template_validate_yaml(self):
ret = self.heat('template-validate -f %s' % self.heat_template_path)
# On success template-validate returns a json representation
# of the template parameters
self.assertIsInstance(json.loads(ret), dict)
+ @test.idempotent_id('35241014-16ea-4cb6-ad3e-4ee5f41446de')
def test_heat_template_validate_hot(self):
ret = self.heat('template-validate -f %s' % self.heat_template_path)
self.assertIsInstance(json.loads(ret), dict)
+ @test.idempotent_id('34d43e0a-36dc-4ea8-9b85-0189e3de89d8')
def test_heat_help(self):
self.heat('help')
@tempest.cli.min_client_version(client='heat', version='0.2.7')
+ @test.idempotent_id('c122c08b-839d-49d1-afd1-bc546b2d18d3')
def test_heat_bash_completion(self):
self.heat('bash-completion')
+ @test.idempotent_id('1b045e12-2fa0-4895-9282-00668428dfbe')
def test_heat_help_cmd(self):
# Check requesting help for a specific command works
help_text = self.heat('help resource-template')
lines = help_text.split('\n')
self.assertFirstLineStartsWith(lines, 'usage: heat resource-template')
+ @test.idempotent_id('c7837f8f-d0a8-47fd-b75b-14ba3e3fa9a2')
def test_heat_version(self):
self.heat('', flags='--version')
diff --git a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
index f9bf8b2..85db596 100644
--- a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
@@ -43,15 +43,19 @@
return self.clients.ceilometer(
*args, endpoint_type=CONF.telemetry.endpoint_type, **kwargs)
+ @test.idempotent_id('ab717d43-a9c4-4dcf-bad8-c4777933a970')
def test_ceilometer_meter_list(self):
self.ceilometer('meter-list')
@test.attr(type='slow')
+ @test.idempotent_id('fe2e52a4-a99b-426e-a52d-d0bde50f3e4c')
def test_ceilometer_resource_list(self):
self.ceilometer('resource-list')
+ @test.idempotent_id('eede695c-f3bf-449f-a420-02f3cc426d52')
def test_ceilometermeter_alarm_list(self):
self.ceilometer('alarm-list')
+ @test.idempotent_id('0586bcc4-8e35-415f-8f23-77b590042684')
def test_ceilometer_version(self):
self.ceilometer('', flags='--version')
diff --git a/tempest/cli/simple_read_only/volume/test_cinder.py b/tempest/cli/simple_read_only/volume/test_cinder.py
index c2e0a42..cb29cc8 100644
--- a/tempest/cli/simple_read_only/volume/test_cinder.py
+++ b/tempest/cli/simple_read_only/volume/test_cinder.py
@@ -22,6 +22,7 @@
from tempest import cli
from tempest import clients
from tempest import config
+from tempest import test
CONF = config.CONF
@@ -51,25 +52,30 @@
endpoint_type=CONF.volume.endpoint_type,
**kwargs)
+ @test.idempotent_id('229bc6dc-d804-4668-b753-b590caf63061')
def test_cinder_fake_action(self):
self.assertRaises(exceptions.CommandFailed,
self.cinder,
'this-does-not-exist')
+ @test.idempotent_id('77140216-14db-4fc5-a246-e2a587e9e99b')
def test_cinder_absolute_limit_list(self):
roles = self.parser.listing(self.cinder('absolute-limits'))
self.assertTableStruct(roles, ['Name', 'Value'])
+ @test.idempotent_id('2206b9ce-1a36-4a0a-a129-e5afc7cee1dd')
def test_cinder_backup_list(self):
backup_list = self.parser.listing(self.cinder('backup-list'))
self.assertTableStruct(backup_list, ['ID', 'Volume ID', 'Status',
'Name', 'Size', 'Object Count',
'Container'])
+ @test.idempotent_id('c7f50346-cd99-4e0b-953f-796ff5f47295')
def test_cinder_extra_specs_list(self):
extra_specs_list = self.parser.listing(self.cinder('extra-specs-list'))
self.assertTableStruct(extra_specs_list, ['ID', 'Name', 'extra_specs'])
+ @test.idempotent_id('9de694cb-b40b-442c-a30c-5f9873e144f7')
def test_cinder_volumes_list(self):
list = self.parser.listing(self.cinder('list'))
self.assertTableStruct(list, ['ID', 'Status', 'Name', 'Size',
@@ -82,29 +88,34 @@
'list',
params='--all-tenants bad')
+ @test.idempotent_id('56f7c15c-ee82-4f23-bbe8-ce99b66da493')
def test_cinder_quota_class_show(self):
"""This CLI can accept and string as param."""
roles = self.parser.listing(self.cinder('quota-class-show',
params='abc'))
self.assertTableStruct(roles, ['Property', 'Value'])
+ @test.idempotent_id('a919a811-b7f0-47a7-b4e5-f3eb674dd200')
def test_cinder_quota_defaults(self):
"""This CLI can accept and string as param."""
roles = self.parser.listing(self.cinder('quota-defaults',
params=self.admin_tenant_id))
self.assertTableStruct(roles, ['Property', 'Value'])
+ @test.idempotent_id('18166673-ffa8-4df3-b60c-6375532288bc')
def test_cinder_quota_show(self):
"""This CLI can accept and string as param."""
roles = self.parser.listing(self.cinder('quota-show',
params=self.admin_tenant_id))
self.assertTableStruct(roles, ['Property', 'Value'])
+ @test.idempotent_id('b2c66ed9-ca96-4dc4-94cc-8083e664e516')
def test_cinder_rate_limits(self):
rate_limits = self.parser.listing(self.cinder('rate-limits'))
self.assertTableStruct(rate_limits, ['Verb', 'URI', 'Value', 'Remain',
'Unit', 'Next_Available'])
+ @test.idempotent_id('7a19955b-807c-481a-a2ee-9d76733eac28')
@testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
'Volume snapshot not available.')
def test_cinder_snapshot_list(self):
@@ -112,22 +123,27 @@
self.assertTableStruct(snapshot_list, ['ID', 'Volume ID', 'Status',
'Name', 'Size'])
+ @test.idempotent_id('6e54ecd9-7ba9-490d-8e3b-294b67139e73')
def test_cinder_type_list(self):
type_list = self.parser.listing(self.cinder('type-list'))
self.assertTableStruct(type_list, ['ID', 'Name'])
+ @test.idempotent_id('2c363583-24a0-4980-b9cb-b50c0d241e82')
def test_cinder_list_extensions(self):
roles = self.parser.listing(self.cinder('list-extensions'))
self.assertTableStruct(roles, ['Name', 'Summary', 'Alias', 'Updated'])
+ @test.idempotent_id('691bd6df-30ad-4be7-927b-a02d62aaa38a')
def test_cinder_credentials(self):
credentials = self.parser.listing(self.cinder('credentials'))
self.assertTableStruct(credentials, ['User Credentials', 'Value'])
+ @test.idempotent_id('5c6d71a3-4904-4a3a-aec9-7fd4aa830e95')
def test_cinder_availability_zone_list(self):
zone_list = self.parser.listing(self.cinder('availability-zone-list'))
self.assertTableStruct(zone_list, ['Name', 'Status'])
+ @test.idempotent_id('9b0fd5a6-f955-42b9-a42f-6f542a80b9a3')
def test_cinder_endpoints(self):
out = self.cinder('endpoints')
tables = self.parser.tables(out)
@@ -136,28 +152,34 @@
self.assertTrue(2 >= len(headers))
self.assertEqual('Value', headers[1])
+ @test.idempotent_id('301b5ae1-9591-4e9f-999c-d525a9bdf822')
def test_cinder_service_list(self):
service_list = self.parser.listing(self.cinder('service-list'))
self.assertTableStruct(service_list, ['Binary', 'Host', 'Zone',
'Status', 'State', 'Updated_at'])
+ @test.idempotent_id('7260ae52-b462-461e-9048-36d0bccf92c6')
def test_cinder_transfer_list(self):
transfer_list = self.parser.listing(self.cinder('transfer-list'))
self.assertTableStruct(transfer_list, ['ID', 'Volume ID', 'Name'])
+ @test.idempotent_id('0976dea8-14f3-45a9-8495-3617fc4fbb13')
def test_cinder_bash_completion(self):
self.cinder('bash-completion')
+ @test.idempotent_id('b7c00361-be80-4512-8735-5f98fc54f2a9')
def test_cinder_qos_list(self):
qos_list = self.parser.listing(self.cinder('qos-list'))
self.assertTableStruct(qos_list, ['ID', 'Name', 'Consumer', 'specs'])
+ @test.idempotent_id('2e92dc6e-22b5-4d94-abfc-b543b0c50a89')
def test_cinder_encryption_type_list(self):
encrypt_list = self.parser.listing(self.cinder('encryption-type-list'))
self.assertTableStruct(encrypt_list, ['Volume Type ID', 'Provider',
'Cipher', 'Key Size',
'Control Location'])
+ @test.idempotent_id('0ee6cb4c-8de6-4811-a7be-7f4bb75b80cc')
def test_admin_help(self):
help_text = self.cinder('help')
lines = help_text.split('\n')
@@ -178,15 +200,19 @@
# Optional arguments:
+ @test.idempotent_id('2fd6f530-183c-4bda-8918-1e59e36c26b9')
def test_cinder_version(self):
self.cinder('', flags='--version')
+ @test.idempotent_id('306bac51-c443-4426-a6cf-583a953fcd68')
def test_cinder_debug_list(self):
self.cinder('list', flags='--debug')
+ @test.idempotent_id('6d97fcd2-5dd1-429d-af70-030c949d86cd')
def test_cinder_retries_list(self):
self.cinder('list', flags='--retries 3')
+ @test.idempotent_id('95a2850c-35b4-4159-bb93-51647a5ad232')
def test_cinder_region_list(self):
region = CONF.volume.region
if not region:
diff --git a/tempest/clients.py b/tempest/clients.py
index 03928ba..63bc117 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -15,7 +15,7 @@
import copy
-from tempest import auth
+from tempest.common import cred_provider
from tempest.common import negative_rest_client
from tempest import config
from tempest import manager
@@ -29,6 +29,8 @@
AggregatesClientJSON
from tempest.services.compute.json.availability_zone_client import \
AvailabilityZoneClientJSON
+from tempest.services.compute.json.baremetal_nodes_client import \
+ BaremetalNodesClientJSON
from tempest.services.compute.json.certificates_client import \
CertificatesClientJSON
from tempest.services.compute.json.extensions_client import \
@@ -64,15 +66,17 @@
TenantUsagesClientJSON
from tempest.services.compute.json.volumes_extensions_client import \
VolumesExtensionsClientJSON
-from tempest.services.data_processing.v1_1.client import DataProcessingClient
+from tempest.services.data_processing.v1_1.data_processing_client import \
+ DataProcessingClient
from tempest.services.database.json.flavors_client import \
DatabaseFlavorsClientJSON
from tempest.services.database.json.limits_client import \
DatabaseLimitsClientJSON
from tempest.services.database.json.versions_client import \
DatabaseVersionsClientJSON
-from tempest.services.identity.json.identity_client import IdentityClientJSON
-from tempest.services.identity.json.token_client import TokenClientJSON
+from tempest.services.identity.v2.json.identity_client import \
+ IdentityClientJSON
+from tempest.services.identity.v2.json.token_client import TokenClientJSON
from tempest.services.identity.v3.json.credentials_client import \
CredentialsClientJSON
from tempest.services.identity.v3.json.endpoints_client import \
@@ -155,10 +159,7 @@
}
default_params_with_timeout_values.update(default_params)
- def __init__(self, credentials=None, interface='json', service=None):
- # Set interface and client type first
- self.interface = interface
- # super cares for credentials validation
+ def __init__(self, credentials=None, service=None):
super(Manager, self).__init__(credentials=credentials)
self._set_compute_clients()
@@ -194,8 +195,22 @@
endpoint_type=CONF.telemetry.endpoint_type,
**self.default_params_with_timeout_values)
if CONF.service_available.glance:
- self.image_client = ImageClientJSON(self.auth_provider)
- self.image_client_v2 = ImageClientV2JSON(self.auth_provider)
+ self.image_client = ImageClientJSON(
+ self.auth_provider,
+ CONF.image.catalog_type,
+ CONF.image.region or CONF.identity.region,
+ endpoint_type=CONF.image.endpoint_type,
+ build_interval=CONF.image.build_interval,
+ build_timeout=CONF.image.build_timeout,
+ **self.default_params)
+ self.image_client_v2 = ImageClientV2JSON(
+ self.auth_provider,
+ CONF.image.catalog_type,
+ CONF.image.region or CONF.identity.region,
+ endpoint_type=CONF.image.endpoint_type,
+ build_interval=CONF.image.build_interval,
+ build_timeout=CONF.image.build_timeout,
+ **self.default_params)
self.orchestration_client = OrchestrationClient(
self.auth_provider,
CONF.orchestration.catalog_type,
@@ -204,6 +219,12 @@
build_interval=CONF.orchestration.build_interval,
build_timeout=CONF.orchestration.build_timeout,
**self.default_params)
+ self.data_processing_client = DataProcessingClient(
+ self.auth_provider,
+ CONF.data_processing.catalog_type,
+ CONF.identity.region,
+ endpoint_type=CONF.data_processing.endpoint_type,
+ **self.default_params_with_timeout_values)
self.negative_client = negative_rest_client.NegativeRestClient(
self.auth_provider, service)
@@ -214,8 +235,6 @@
self.credentials.tenant_name)
self.ec2api_client = botoclients.APIClientEC2(*ec2_client_args)
self.s3_client = botoclients.ObjectClientS3(*ec2_client_args)
- self.data_processing_client = DataProcessingClient(
- self.auth_provider)
def _set_compute_clients(self):
params = {
@@ -235,7 +254,11 @@
SecurityGroupDefaultRulesClientJSON(self.auth_provider, **params))
self.certificates_client = CertificatesClientJSON(self.auth_provider,
**params)
- self.servers_client = ServersClientJSON(self.auth_provider, **params)
+ self.servers_client = ServersClientJSON(
+ self.auth_provider,
+ enable_instance_password=CONF.compute_feature_enabled
+ .enable_instance_password,
+ **params)
self.limits_client = LimitsClientJSON(self.auth_provider, **params)
self.images_client = ImagesClientJSON(self.auth_provider, **params)
self.keypairs_client = KeyPairsClientJSON(self.auth_provider, **params)
@@ -267,6 +290,8 @@
InstanceUsagesAuditLogClientJSON(self.auth_provider, **params)
self.tenant_networks_client = \
TenantNetworksClientJSON(self.auth_provider, **params)
+ self.baremetal_nodes_client = BaremetalNodesClientJSON(
+ self.auth_provider, **params)
# NOTE: The following client needs special timeout values because
# the API is a proxy for the other component.
@@ -296,16 +321,30 @@
**self.default_params_with_timeout_values)
def _set_identity_clients(self):
- self.identity_client = IdentityClientJSON(self.auth_provider)
- self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider)
- self.endpoints_client = EndPointClientJSON(self.auth_provider)
- self.service_client = ServiceClientJSON(self.auth_provider)
- self.policy_client = PolicyClientJSON(self.auth_provider)
- self.region_client = RegionClientJSON(self.auth_provider)
- self.token_client = TokenClientJSON()
+ params = {
+ 'service': CONF.identity.catalog_type,
+ 'region': CONF.identity.region,
+ 'endpoint_type': 'adminURL'
+ }
+ params.update(self.default_params_with_timeout_values)
+
+ self.identity_client = IdentityClientJSON(self.auth_provider,
+ **params)
+ self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider,
+ **params)
+ self.endpoints_client = EndPointClientJSON(self.auth_provider,
+ **params)
+ self.service_client = ServiceClientJSON(self.auth_provider, **params)
+ self.policy_client = PolicyClientJSON(self.auth_provider, **params)
+ self.region_client = RegionClientJSON(self.auth_provider, **params)
+ self.credentials_client = CredentialsClientJSON(self.auth_provider,
+ **params)
+ # Token clients do not use the catalog. They only need default_params.
+ self.token_client = TokenClientJSON(CONF.identity.uri,
+ **self.default_params)
if CONF.identity_feature_enabled.api_v3:
- self.token_v3_client = V3TokenClientJSON()
- self.credentials_client = CredentialsClientJSON(self.auth_provider)
+ self.token_v3_client = V3TokenClientJSON(CONF.identity.uri_v3,
+ **self.default_params)
def _set_volume_clients(self):
params = {
@@ -330,9 +369,12 @@
**params)
self.snapshots_v2_client = SnapshotsV2ClientJSON(self.auth_provider,
**params)
- self.volumes_client = VolumesClientJSON(self.auth_provider, **params)
- self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider,
- **params)
+ self.volumes_client = VolumesClientJSON(
+ self.auth_provider, default_volume_size=CONF.volume.volume_size,
+ **params)
+ self.volumes_v2_client = VolumesV2ClientJSON(
+ self.auth_provider, default_volume_size=CONF.volume.volume_size,
+ **params)
self.volume_types_client = VolumeTypesClientJSON(self.auth_provider,
**params)
self.volume_services_client = VolumesServicesClientJSON(
@@ -376,8 +418,8 @@
managed client objects
"""
- def __init__(self, interface='json', service=None):
+ def __init__(self, service=None):
super(AdminManager, self).__init__(
- credentials=auth.get_default_credentials('identity_admin'),
- interface=interface,
+ credentials=cred_provider.get_configured_credentials(
+ 'identity_admin'),
service=service)
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 28992b9..669f506 100755
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -54,9 +54,9 @@
import json
import sys
-from tempest import auth
from tempest import clients
from tempest.cmd import cleanup_service
+from tempest.common import cred_provider
from tempest import config
from tempest.openstack.common import log as logging
@@ -159,7 +159,8 @@
kwargs = {"username": CONF.identity.admin_username,
"password": CONF.identity.admin_password,
"tenant_name": tenant['name']}
- mgr = clients.Manager(credentials=auth.get_credentials(**kwargs))
+ mgr = clients.Manager(credentials=cred_provider.get_credentials(
+ **kwargs))
kwargs = {'data': tenant_data,
'is_dry_run': is_dry_run,
'saved_state_json': None,
@@ -221,7 +222,7 @@
needs_role = False
LOG.debug("User already had admin privilege for this tenant")
if needs_role:
- LOG.debug("Adding admin priviledge for : %s" % tenant_id)
+ LOG.debug("Adding admin privilege for : %s" % tenant_id)
id_cl.assign_user_role(tenant_id, self.admin_id,
self.admin_role_id)
self.admin_role_added.append(tenant_id)
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 9c4a5dc..7b217bb 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -168,7 +168,7 @@
def list(self):
client = self.client
- _, servers_body = client.list_servers()
+ servers_body = client.list_servers()
servers = servers_body['servers']
LOG.debug("List count, %s Servers" % len(servers))
return servers
@@ -192,7 +192,7 @@
def list(self):
client = self.client
- _, sgs = client.list_server_groups()
+ sgs = client.list_server_groups()
LOG.debug("List count, %s Server Groups" % len(sgs))
return sgs
@@ -297,7 +297,7 @@
def list(self):
client = self.client
- _, floating_ips = client.list_floating_ips()
+ floating_ips = client.list_floating_ips()
LOG.debug("List count, %s Floating IPs" % len(floating_ips))
return floating_ips
@@ -833,9 +833,9 @@
def save_state(self):
flavors = self.list()
- flavor_data = self.data['flavors'] = {}
+ self.data['flavors'] = {}
for flavor in flavors:
- flavor_data[flavor['id']] = flavor['name']
+ self.data['flavors'][flavor['id']] = flavor['name']
class ImageService(BaseService):
@@ -871,9 +871,9 @@
def save_state(self):
images = self.list()
- image_data = self.data['images'] = {}
+ self.data['images'] = {}
for image in images:
- image_data[image['id']] = image['name']
+ self.data['images'][image['id']] = image['name']
class IdentityService(BaseService):
@@ -919,9 +919,9 @@
def save_state(self):
users = self.list()
- user_data = self.data['users'] = {}
+ self.data['users'] = {}
for user in users:
- user_data[user['id']] = user['name']
+ self.data['users'][user['id']] = user['name']
class RoleService(IdentityService):
@@ -958,9 +958,9 @@
def save_state(self):
roles = self.list()
- role_data = self.data['roles'] = {}
+ self.data['roles'] = {}
for role in roles:
- role_data[role['id']] = role['name']
+ self.data['roles'][role['id']] = role['name']
class TenantService(IdentityService):
@@ -996,9 +996,9 @@
def save_state(self):
tenants = self.list()
- tenant_data = self.data['tenants'] = {}
+ self.data['tenants'] = {}
for tenant in tenants:
- tenant_data[tenant['id']] = tenant['name']
+ self.data['tenants'][tenant['id']] = tenant['name']
class DomainService(BaseService):
@@ -1034,9 +1034,9 @@
def save_state(self):
domains = self.list()
- domain_data = self.data['domains'] = {}
+ self.data['domains'] = {}
for domain in domains:
- domain_data[domain['id']] = domain['name']
+ self.data['domains'][domain['id']] = domain['name']
def get_tenant_cleanup_services():
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 889b2dd..4c09bd2 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -110,17 +110,17 @@
import unittest
import netaddr
+from tempest_lib import exceptions as lib_exc
import yaml
import tempest.auth
from tempest import config
-from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.openstack.common import timeutils
from tempest.services.compute.json import flavors_client
from tempest.services.compute.json import security_groups_client
from tempest.services.compute.json import servers_client
-from tempest.services.identity.json import identity_client
+from tempest.services.identity.v2.json import identity_client
from tempest.services.image.v2.json import image_client
from tempest.services.network.json import network_client
from tempest.services.object_storage import container_client
@@ -176,8 +176,20 @@
username=user,
password=pw,
tenant_name=tenant)
- _auth = tempest.auth.KeystoneV2AuthProvider(_creds)
- self.identity = identity_client.IdentityClientJSON(_auth)
+ auth_provider_params = {
+ 'disable_ssl_certificate_validation':
+ CONF.identity.disable_ssl_certificate_validation,
+ 'ca_certs': CONF.identity.ca_certificates_file,
+ 'trace_requests': CONF.debug.trace_requests
+ }
+ _auth = tempest.auth.KeystoneV2AuthProvider(
+ _creds, CONF.identity.uri, **auth_provider_params)
+ self.identity = identity_client.IdentityClientJSON(
+ _auth,
+ CONF.identity.catalog_type,
+ CONF.identity.region,
+ endpoint_type='adminURL',
+ **default_params_with_timeout_values)
self.servers = servers_client.ServersClientJSON(_auth,
**compute_params)
self.flavors = flavors_client.FlavorsClientJSON(_auth,
@@ -188,7 +200,14 @@
**object_storage_params)
self.containers = container_client.ContainerClient(
_auth, **object_storage_params)
- self.images = image_client.ImageClientV2JSON(_auth)
+ self.images = image_client.ImageClientV2JSON(
+ _auth,
+ CONF.image.catalog_type,
+ CONF.image.region or CONF.identity.region,
+ endpoint_type=CONF.image.endpoint_type,
+ build_interval=CONF.image.build_interval,
+ build_timeout=CONF.image.build_timeout,
+ **default_params)
self.telemetry = telemetry_client.TelemetryClientJSON(
_auth,
CONF.telemetry.catalog_type,
@@ -232,9 +251,6 @@
LOG.error("%s not found in USERS: %s" % (name, USERS))
-def resp_ok(response):
- return 200 >= int(response['status']) < 300
-
###################
#
# TENANTS
@@ -297,7 +313,7 @@
USERS[user]['tenant_id'],
USERS[user]['id'],
role['id'])
- except exceptions.Conflict:
+ except lib_exc.Conflict:
# don't care if it's already assigned
pass
@@ -313,14 +329,14 @@
for u in users:
try:
tenant = admin.identity.get_tenant_by_name(u['tenant'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.error("Tenant: %s - not found" % u['tenant'])
continue
try:
admin.identity.get_user_by_username(tenant['id'], u['name'])
LOG.warn("User '%s' already exists in this environment"
% u['name'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
admin.identity.create_user(
u['name'], u['pass'], tenant['id'],
"%s@%s" % (u['name'], tenant['id']),
@@ -405,8 +421,7 @@
# on the cloud. We don't care about the results except that it
# remains authorized.
client = client_for_user(user['name'])
- resp, body = client.servers.list_servers()
- self.assertEqual(resp['status'], '200')
+ client.servers.list_servers()
def check_objects(self):
"""Check that the objects created are still there."""
@@ -432,7 +447,7 @@
found,
"Couldn't find expected server %s" % server['name'])
- r, found = client.servers.get_server(found['id'])
+ found = client.servers.get_server(found['id'])
# validate neutron is enabled and ironic disabled:
if (CONF.service_available.neutron and
not CONF.baremetal.driver_enabled):
@@ -707,7 +722,7 @@
cidr=subnet['range'],
name=subnet['name'],
ip_version=ip_version)
- except exceptions.BadRequest as e:
+ except lib_exc.BadRequest as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
if not is_overlapping_cidr:
raise
@@ -780,7 +795,7 @@
#######################
def _get_server_by_name(client, name):
- r, body = client.servers.list_servers()
+ body = client.servers.list_servers()
for server in body['servers']:
if name == server['name']:
return server
@@ -816,7 +831,7 @@
client.networks, 'networks', x)['id'])
kwargs['networks'] = [{'uuid': get_net_id(network)}
for network in server['networks']]
- resp, body = client.servers.create_server(
+ body = client.servers.create_server(
server['name'], image_id, flavor_id, **kwargs)
server_id = body['id']
client.servers.wait_for_server_status(server_id, 'ACTIVE')
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 65a3a95..697965f 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -154,7 +154,7 @@
def verify_extensions(os, service, results):
extensions_client = get_extension_client(os, service)
- if service == 'neutron' or service == 'cinder':
+ if service != 'swift':
resp = extensions_client.list_extensions()
else:
__, resp = extensions_client.list_extensions()
@@ -327,7 +327,7 @@
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- os = clients.AdminManager(interface='json')
+ os = clients.AdminManager()
services = check_service_availability(os, update)
results = {}
for service in ['nova', 'cinder', 'neutron', 'swift']:
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 66285e4..e21a85e 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -17,7 +17,6 @@
import yaml
-from tempest import auth
from tempest.common import cred_provider
from tempest import config
from tempest import exceptions
@@ -38,6 +37,7 @@
def __init__(self, name):
super(Accounts, self).__init__(name)
+ self.name = name
if os.path.isfile(CONF.auth.test_accounts_file):
accounts = read_accounts_yaml(CONF.auth.test_accounts_file)
self.use_default_creds = False
@@ -71,7 +71,8 @@
def _create_hash_file(self, hash_string):
path = os.path.join(os.path.join(self.accounts_dir, hash_string))
if not os.path.isfile(path):
- open(path, 'w').close()
+ with open(path, 'w') as fd:
+ fd.write(self.name)
return True
return False
@@ -82,11 +83,18 @@
# Create File from first hash (since none are in use)
self._create_hash_file(hashes[0])
return hashes[0]
+ names = []
for _hash in hashes:
res = self._create_hash_file(_hash)
if res:
return _hash
- msg = 'Insufficient number of users provided'
+ else:
+ path = os.path.join(os.path.join(self.accounts_dir,
+ _hash))
+ with open(path, 'r') as fd:
+ names.append(fd.read())
+ msg = ('Insufficient number of users provided. %s have allocated all '
+ 'the credentials for this allocation request' % ','.join(names))
raise exceptions.InvalidConfiguration(msg)
def _get_creds(self):
@@ -101,7 +109,7 @@
hash_path = os.path.join(self.accounts_dir, hash_string)
if not os.path.isfile(hash_path):
LOG.warning('Expected an account lock file %s to remove, but '
- 'one did not exist')
+ 'one did not exist' % hash_path)
else:
os.remove(hash_path)
if not os.listdir(self.accounts_dir):
@@ -109,9 +117,9 @@
def get_hash(self, creds):
for _hash in self.hash_dict:
- # Comparing on the attributes that are expected in the YAML
+ # Comparing on the attributes that were read from the YAML
if all([getattr(creds, k) == self.hash_dict[_hash][k] for k in
- creds.CONF_ATTRIBUTES]):
+ creds.get_init_attributes()]):
return _hash
raise AttributeError('Invalid credentials %s' % creds)
@@ -123,7 +131,7 @@
if self.isolated_creds.get('primary'):
return self.isolated_creds.get('primary')
creds = self._get_creds()
- primary_credential = auth.get_credentials(**creds)
+ primary_credential = cred_provider.get_credentials(**creds)
self.isolated_creds['primary'] = primary_credential
return primary_credential
@@ -131,7 +139,7 @@
if self.isolated_creds.get('alt'):
return self.isolated_creds.get('alt')
creds = self._get_creds()
- alt_credential = auth.get_credentials(**creds)
+ alt_credential = cred_provider.get_credentials(**creds)
self.isolated_creds['alt'] = alt_credential
return alt_credential
@@ -189,9 +197,10 @@
return self.isolated_creds.get('primary')
if not self.use_default_creds:
creds = self.get_creds(0)
- primary_credential = auth.get_credentials(**creds)
+ primary_credential = cred_provider.get_credentials(**creds)
else:
- primary_credential = auth.get_default_credentials('user')
+ primary_credential = cred_provider.get_configured_credentials(
+ 'user')
self.isolated_creds['primary'] = primary_credential
return primary_credential
@@ -200,9 +209,10 @@
return self.isolated_creds.get('alt')
if not self.use_default_creds:
creds = self.get_creds(1)
- alt_credential = auth.get_credentials(**creds)
+ alt_credential = cred_provider.get_credentials(**creds)
else:
- alt_credential = auth.get_default_credentials('alt_user')
+ alt_credential = cred_provider.get_configured_credentials(
+ 'alt_user')
self.isolated_creds['alt'] = alt_credential
return alt_credential
@@ -210,4 +220,5 @@
self.isolated_creds = {}
def get_admin_creds(self):
- return auth.get_default_credentials("identity_admin", fill_in=False)
+ return cred_provider.get_configured_credentials(
+ "identity_admin", fill_in=False)
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index c5be0c0..033410e 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -16,17 +16,78 @@
import six
+from tempest import auth
from tempest import config
+from tempest import exceptions
from tempest.openstack.common import log as logging
CONF = config.CONF
LOG = logging.getLogger(__name__)
+# Type of credentials available from configuration
+CREDENTIAL_TYPES = {
+ 'identity_admin': ('identity', 'admin'),
+ 'user': ('identity', None),
+ 'alt_user': ('identity', 'alt')
+}
+
+
+# Read credentials from configuration, builds a Credentials object
+# based on the specified or configured version
+def get_configured_credentials(credential_type, fill_in=True,
+ identity_version=None):
+ identity_version = identity_version or CONF.identity.auth_version
+ if identity_version not in ('v2', 'v3'):
+ raise exceptions.InvalidConfiguration(
+ 'Unsupported auth version: %s' % identity_version)
+ if credential_type not in CREDENTIAL_TYPES:
+ raise exceptions.InvalidCredentials()
+ conf_attributes = ['username', 'password', 'tenant_name']
+ if identity_version == 'v3':
+ conf_attributes.append('domain_name')
+ # Read the parts of credentials from config
+ params = {}
+ section, prefix = CREDENTIAL_TYPES[credential_type]
+ for attr in conf_attributes:
+ _section = getattr(CONF, section)
+ if prefix is None:
+ params[attr] = getattr(_section, attr)
+ else:
+ params[attr] = getattr(_section, prefix + "_" + attr)
+ # Build and validate credentials. We are reading configured credentials,
+ # so validate them even if fill_in is False
+ credentials = get_credentials(fill_in=fill_in, **params)
+ if not fill_in:
+ if not credentials.is_valid():
+ msg = ("The %s credentials are incorrectly set in the config file."
+ " Double check that all required values are assigned" %
+ credential_type)
+ raise exceptions.InvalidConfiguration(msg)
+ return credentials
+
+
+# Wrapper around auth.get_credentials to use the configured identity version
+# is none is specified
+def get_credentials(fill_in=True, identity_version=None, **kwargs):
+ identity_version = identity_version or CONF.identity.auth_version
+ # In case of "v3" add the domain from config if not specified
+ if identity_version == 'v3':
+ domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
+ if 'domain' in x)
+ if not domain_fields.intersection(kwargs.keys()):
+ kwargs['user_domain_name'] = CONF.identity.admin_domain_name
+ auth_url = CONF.identity.uri_v3
+ else:
+ auth_url = CONF.identity.uri
+ return auth.get_credentials(auth_url,
+ fill_in=fill_in,
+ identity_version=identity_version,
+ **kwargs)
+
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
- def __init__(self, name, interface='json', password='pass',
- network_resources=None):
+ def __init__(self, name, password='pass', network_resources=None):
self.name = name
@abc.abstractmethod
diff --git a/tempest/common/credentials.py b/tempest/common/credentials.py
index 08b592f..40761c8 100644
--- a/tempest/common/credentials.py
+++ b/tempest/common/credentials.py
@@ -12,8 +12,10 @@
# limitations under the License.
from tempest.common import accounts
+from tempest.common import cred_provider
from tempest.common import isolated_creds
from tempest import config
+from tempest import exceptions
CONF = config.CONF
@@ -37,3 +39,31 @@
return accounts.Accounts(name=name)
else:
return accounts.NotLockingAccounts(name=name)
+
+
+# We want a helper function here to check and see if admin credentials
+# are available so we can do a single call from skip_checks if admin
+# creds area vailable.
+def is_admin_available():
+ is_admin = True
+ # In the case of a pre-provisioned account, if even if creds were
+ # configured, the admin credentials won't be available
+ if (CONF.auth.locking_credentials_provider and
+ not CONF.auth.allow_tenant_isolation):
+ is_admin = False
+ else:
+ try:
+ cred_provider.get_configured_credentials('identity_admin')
+ # NOTE(mtreinish) This should never be caught because of the if above.
+ # NotImplementedError is only raised if admin credentials are requested
+ # and the locking test accounts cred provider is being used.
+ except NotImplementedError:
+ is_admin = False
+ # NOTE(mtreinish): This will be raised by the non-locking accounts
+ # provider if there aren't admin credentials provided in the config
+ # file. This exception originates from the auth call to get configured
+ # credentials
+ except exceptions.InvalidConfiguration:
+ is_admin = False
+
+ return is_admin
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index a663931..3eed689 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -13,8 +13,8 @@
# under the License.
import netaddr
+from tempest_lib import exceptions as lib_exc
-from tempest import auth
from tempest import clients
from tempest.common import cred_provider
from tempest.common.utils import data_utils
@@ -28,15 +28,12 @@
class IsolatedCreds(cred_provider.CredentialProvider):
- def __init__(self, name, interface='json', password='pass',
- network_resources=None):
- super(IsolatedCreds, self).__init__(name, interface, password,
- network_resources)
+ def __init__(self, name, password='pass', network_resources=None):
+ super(IsolatedCreds, self).__init__(name, password, network_resources)
self.network_resources = network_resources
self.isolated_creds = {}
self.isolated_net_resources = {}
self.ports = []
- self.interface = interface
self.password = password
self.identity_admin_client, self.network_admin_client = (
self._get_admin_clients())
@@ -48,7 +45,7 @@
identity
network
"""
- os = clients.AdminManager(interface=self.interface)
+ os = clients.AdminManager()
return os.identity_client, os.network_client
def _create_tenant(self, name, description):
@@ -81,7 +78,7 @@
role = next(r for r in roles if r['name'] == role_name)
except StopIteration:
msg = 'No "%s" role found' % role_name
- raise exceptions.NotFound(msg)
+ raise lib_exc.NotFound(msg)
self.identity_admin_client.assign_user_role(tenant['id'], user['id'],
role['id'])
@@ -129,7 +126,7 @@
return self._get_credentials(user, tenant)
def _get_credentials(self, user, tenant):
- return auth.get_credentials(
+ return cred_provider.get_credentials(
username=user['name'], user_id=user['id'],
tenant_name=tenant['name'], tenant_id=tenant['id'],
password=self.password)
@@ -201,7 +198,7 @@
tenant_id=tenant_id,
ip_version=4)
break
- except exceptions.BadRequest as e:
+ except lib_exc.BadRequest as e:
if 'overlaps with another subnet' not in str(e):
raise
else:
@@ -282,7 +279,7 @@
net_client = self.network_admin_client
try:
net_client.delete_router(router_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn('router with name: %s not found for delete' %
router_name)
@@ -290,7 +287,7 @@
net_client = self.network_admin_client
try:
net_client.delete_subnet(subnet_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn('subnet with name: %s not found for delete' %
subnet_name)
@@ -298,7 +295,7 @@
net_client = self.network_admin_client
try:
net_client.delete_network(network_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn('network with name: %s not found for delete' %
network_name)
@@ -310,7 +307,7 @@
for secgroup in secgroups_to_delete:
try:
net_client.delete_security_group(secgroup['id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn('Security group %s, id %s not found for clean-up' %
(secgroup['name'], secgroup['id']))
@@ -326,7 +323,7 @@
try:
net_client.remove_router_interface_with_subnet_id(
router['id'], subnet['id'])
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn('router with name: %s not found for delete' %
router['name'])
self._clear_isolated_router(router['id'], router['name'])
@@ -336,6 +333,7 @@
if (not self.network_resources or
self.network_resources.get('network')):
self._clear_isolated_network(network['id'], network['name'])
+ self.isolated_net_resources = {}
def clear_isolated_creds(self):
if not self.isolated_creds:
@@ -344,14 +342,15 @@
for creds in self.isolated_creds.itervalues():
try:
self._delete_user(creds.user_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn("user with name: %s not found for delete" %
creds.username)
try:
self._delete_tenant(creds.tenant_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
LOG.warn("tenant with name: %s not found for delete" %
creds.tenant_name)
+ self.isolated_creds = {}
def is_multi_user(self):
return True
diff --git a/tempest/common/service_client.py b/tempest/common/service_client.py
index 69e25e2..fde05af 100644
--- a/tempest/common/service_client.py
+++ b/tempest/common/service_client.py
@@ -16,7 +16,6 @@
from tempest_lib import exceptions as lib_exceptions
from tempest import config
-from tempest import exceptions
CONF = config.CONF
@@ -59,22 +58,12 @@
method, url,
extra_headers=extra_headers,
headers=headers, body=body)
- except lib_exceptions.Unauthorized as ex:
- raise exceptions.Unauthorized(ex)
- except lib_exceptions.NotFound as ex:
- raise exceptions.NotFound(ex)
- except lib_exceptions.BadRequest as ex:
- raise exceptions.BadRequest(ex)
- except lib_exceptions.Conflict as ex:
- raise exceptions.Conflict(ex)
- except lib_exceptions.OverLimit as ex:
- raise exceptions.OverLimit(ex)
# TODO(oomichi): This is just a workaround for failing gate tests
# when separating Forbidden from Unauthorized in tempest-lib.
# We will need to remove this translation and replace negative tests
# with lib_exceptions.Forbidden in the future.
except lib_exceptions.Forbidden as ex:
- raise exceptions.Unauthorized(ex)
+ raise lib_exceptions.Unauthorized(ex)
class ResponseBody(dict):
@@ -90,10 +79,22 @@
self.response = response
def __str__(self):
- body = super.__str__(self)
+ body = super(ResponseBody, self).__str__()
return "response: %s\nBody: %s" % (self.response, body)
+class ResponseBodyData(object):
+ """Class that wraps an http response and string data into a single value.
+ """
+
+ def __init__(self, response, data):
+ self.response = response
+ self.data = data
+
+ def __str__(self):
+ return "response: %s\nBody: %s" % (self.response, self.data)
+
+
class ResponseBodyList(list):
"""Class that wraps an http response and list body into a single value.
@@ -107,5 +108,5 @@
self.response = response
def __str__(self):
- body = super.__str__(self)
+ body = super(ResponseBodyList, self).__str__()
return "response: %s\nBody: %s" % (self.response, body)
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 6e61c55..1f1414f 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -23,7 +23,7 @@
CONF = config.CONF
-class RemoteClient():
+class RemoteClient(object):
# NOTE(afazekas): It should always get an address instead of server
def __init__(self, server, username, password=None, pkey=None):
@@ -163,4 +163,4 @@
% dhcp_client)
if dhcp_client == 'udhcpc' and not fixed_ip:
raise ValueError("need to set 'fixed_ip' for udhcpc client")
- return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
\ No newline at end of file
+ return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index c77c81e..9b11676 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -32,7 +32,7 @@
# NOTE(afazekas): UNKNOWN status possible on ERROR
# or in a very early stage.
- resp, body = client.get_server(server_id)
+ body = client.get_server(server_id)
old_status = server_status = body['status']
old_task_state = task_state = _get_task_state(body)
start_time = int(time.time())
@@ -59,7 +59,7 @@
return
time.sleep(client.build_interval)
- resp, body = client.get_server(server_id)
+ body = client.get_server(server_id)
server_status = body['status']
task_state = _get_task_state(body)
if (server_status != old_status) or (task_state != old_task_state):
diff --git a/tempest/config.py b/tempest/config.py
index c60434a..a66aa9b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -40,7 +40,7 @@
help="Path to the yaml file that contains the list of "
"credentials to use for running tests"),
cfg.BoolOpt('allow_tenant_isolation',
- default=False,
+ default=True,
help="Allows test cases to create/destroy tenants and "
"users. This option requires that OpenStack Identity "
"API admin credentials are known. If false, isolated "
@@ -455,7 +455,13 @@
cfg.ListOpt('dns_servers',
default=["8.8.8.8", "8.8.4.4"],
help="List of dns servers which should be used"
- " for subnet creation")
+ " for subnet creation"),
+ cfg.StrOpt('port_vnic_type',
+ choices=[None, 'normal', 'direct', 'macvtap'],
+ help="vnic_type to use when Launching instances"
+ " with pre-configured ports."
+ " Supported ports are:"
+ " ['normal','direct','macvtap']"),
]
network_feature_group = cfg.OptGroup(name='network-feature-enabled',
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 7ddeeff..09f7016 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -63,6 +63,10 @@
message = "Invalid service tag"
+class InvalidIdentityVersion(TempestException):
+ message = "Invalid version %(identity_version) of the identity service"
+
+
class TimeoutException(TempestException):
message = "Request timed out"
@@ -151,26 +155,10 @@
message = "The success code is different than the expected one"
-class NotFound(RestClientException):
- message = "Object not found"
-
-
-class Unauthorized(RestClientException):
- message = 'Unauthorized'
-
-
class BadRequest(RestClientException):
message = "Bad request"
-class OverLimit(RestClientException):
- message = "Quota exceeded"
-
-
-class Conflict(RestClientException):
- message = "An object with that identifier already exists"
-
-
class ResponseWithNonEmptyBody(RFCViolation):
message = ("RFC Violation! Response with %(status)d HTTP Status Code "
"MUST NOT have a body")
diff --git a/tempest/manager.py b/tempest/manager.py
index 538b619..a256f25 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import auth
+from tempest.common import cred_provider
from tempest import config
from tempest import exceptions
@@ -39,29 +40,35 @@
"""
self.auth_version = CONF.identity.auth_version
if credentials is None:
- self.credentials = auth.get_default_credentials('user')
+ self.credentials = cred_provider.get_configured_credentials('user')
else:
self.credentials = credentials
# Check if passed or default credentials are valid
if not self.credentials.is_valid():
raise exceptions.InvalidCredentials()
# Creates an auth provider for the credentials
- self.auth_provider = self.get_auth_provider(self.credentials)
+ self.auth_provider = get_auth_provider(self.credentials)
# FIXME(andreaf) unused
self.client_attr_names = []
- @classmethod
- def get_auth_provider_class(cls, credentials):
- if isinstance(credentials, auth.KeystoneV3Credentials):
- return auth.KeystoneV3AuthProvider
- else:
- return auth.KeystoneV2AuthProvider
- def get_auth_provider(self, credentials):
- if credentials is None:
- raise exceptions.InvalidCredentials(
- 'Credentials must be specified')
- auth_provider_class = self.get_auth_provider_class(credentials)
- return auth_provider_class(
- interface=getattr(self, 'interface', None),
- credentials=credentials)
+def get_auth_provider_class(credentials):
+ if isinstance(credentials, auth.KeystoneV3Credentials):
+ return auth.KeystoneV3AuthProvider, CONF.identity.uri_v3
+ else:
+ return auth.KeystoneV2AuthProvider, CONF.identity.uri
+
+
+def get_auth_provider(credentials):
+ default_params = {
+ 'disable_ssl_certificate_validation':
+ CONF.identity.disable_ssl_certificate_validation,
+ 'ca_certs': CONF.identity.ca_certificates_file,
+ 'trace_requests': CONF.debug.trace_requests
+ }
+ if credentials is None:
+ raise exceptions.InvalidCredentials(
+ 'Credentials must be specified')
+ auth_provider_class, auth_url = get_auth_provider_class(
+ credentials)
+ return auth_provider_class(credentials, auth_url, **default_params)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index b1f5cce..968c8ca 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -19,9 +19,10 @@
import netaddr
import six
+from tempest_lib import exceptions as lib_exc
-from tempest import auth
from tempest import clients
+from tempest.common import cred_provider
from tempest.common import credentials
from tempest.common.utils import data_utils
from tempest.common.utils.linux import remote_client
@@ -110,7 +111,7 @@
# Tempest clients return dicts, so there is no common delete
# method available. Using a callable instead
delete_thing(*args, **kwargs)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# If the resource is already missing, mission accomplished.
pass
@@ -186,8 +187,8 @@
LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
name, image, flavor)
- _, server = self.servers_client.create_server(name, image, flavor,
- **create_kwargs)
+ server = self.servers_client.create_server(name, image, flavor,
+ **create_kwargs)
if wait_on_delete:
self.addCleanup(self.servers_client.wait_for_server_termination,
server['id'])
@@ -202,7 +203,7 @@
# The instance retrieved on creation is missing network
# details, necessitating retrieval after it becomes active to
# ensure correct details.
- _, server = self.servers_client.get_server(server['id'])
+ server = self.servers_client.get_server(server['id'])
self.assertEqual(server['name'], name)
return server
@@ -378,13 +379,13 @@
LOG.debug('Console output not supported, cannot log')
return
if not servers:
- _, servers = self.servers_client.list_servers()
+ servers = self.servers_client.list_servers()
servers = servers['servers']
for server in servers:
console_output = self.servers_client.get_console_output(
- server['id'], length=None)
- LOG.debug('Console output for %s\nhead=%s\nbody=\n%s',
- server['id'], console_output[0], console_output[1])
+ server['id'], length=None).data
+ LOG.debug('Console output for %s\nbody=\n%s',
+ server['id'], console_output)
def _log_net_info(self, exc):
# network debug is called as part of ssh init
@@ -417,7 +418,7 @@
def nova_volume_attach(self):
# TODO(andreaf) Device should be here CONF.compute.volume_device_name
volume = self.servers_client.attach_volume(
- self.server['id'], self.volume['id'], '/dev/vdb')[1]
+ self.server['id'], self.volume['id'], '/dev/vdb')
self.assertEqual(self.volume['id'], volume['id'])
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
# Refresh the volume after the attachment
@@ -512,7 +513,7 @@
Nova clients
"""
- _, floating_ip = self.floating_ips_client.create_floating_ip(pool_name)
+ floating_ip = self.floating_ips_client.create_floating_ip(pool_name)
self.addCleanup(self.delete_wrapper,
self.floating_ips_client.delete_floating_ip,
floating_ip['id'])
@@ -628,7 +629,7 @@
try:
result = client.create_subnet(**subnet)
break
- except exceptions.Conflict as e:
+ except lib_exc.Conflict as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
if not is_overlapping_cidr:
raise
@@ -639,14 +640,15 @@
self.addCleanup(self.delete_wrapper, subnet.delete)
return subnet
- def _create_port(self, network, client=None, namestart='port-quotatest'):
+ def _create_port(self, network_id, client=None, namestart='port-quotatest',
+ **kwargs):
if not client:
client = self.network_client
name = data_utils.rand_name(namestart)
result = client.create_port(
name=name,
- network_id=network.id,
- tenant_id=network.tenant_id)
+ network_id=network_id,
+ **kwargs)
self.assertIsNotNone(result, 'Unable to allocate port')
port = net_resources.DeletablePort(client=client,
**result['port'])
@@ -907,6 +909,11 @@
dict(
# ping
protocol='icmp',
+ ),
+ dict(
+ # ipv6-icmp for ping6
+ protocol='icmp',
+ ethertype='IPv6',
)
]
for ruleset in rulesets:
@@ -915,7 +922,7 @@
try:
sg_rule = self._create_security_group_rule(
client=client, secgroup=secgroup, **ruleset)
- except exceptions.Conflict as ex:
+ except lib_exc.Conflict as ex:
# if rule already exist - skip rule and continue
msg = 'Security group rule already exists'
if msg not in ex._error_string:
@@ -1047,6 +1054,66 @@
subnet.add_to_router(router.id)
return network, subnet, router
+ def create_server(self, name=None, image=None, flavor=None,
+ wait_on_boot=True, wait_on_delete=True,
+ create_kwargs=None):
+ vnic_type = CONF.network.port_vnic_type
+
+ # If vnic_type is configured create port for
+ # every network
+ if vnic_type:
+ ports = []
+ networks = []
+ create_port_body = {'binding:vnic_type': vnic_type,
+ 'namestart': 'port-smoke'}
+ if create_kwargs:
+ net_client = create_kwargs.get("network_client",
+ self.network_client)
+
+ # Convert security group names to security group ids
+ # to pass to create_port
+ if create_kwargs.get('security_groups'):
+ security_groups = net_client.list_security_groups().get(
+ 'security_groups')
+ sec_dict = dict([(s['name'], s['id'])
+ for s in security_groups])
+
+ sec_groups_names = [s['name'] for s in create_kwargs[
+ 'security_groups']]
+ security_groups_ids = [sec_dict[s]
+ for s in sec_groups_names]
+
+ if security_groups_ids:
+ create_port_body[
+ 'security_groups'] = security_groups_ids
+ networks = create_kwargs.get('networks')
+ else:
+ net_client = self.network_client
+ # If there are no networks passed to us we look up
+ # for the tenant's private networks and create a port
+ # if there is only one private network. The same behaviour
+ # as we would expect when passing the call to the clients
+ # with no networks
+ if not networks:
+ networks = net_client.list_networks(filters={
+ 'router:external': False})
+ self.assertEqual(1, len(networks),
+ "There is more than one"
+ " network for the tenant")
+ for net in networks:
+ net_id = net['uuid']
+ port = self._create_port(network_id=net_id,
+ client=net_client,
+ **create_port_body)
+ ports.append({'port': port.id})
+ if ports:
+ create_kwargs['networks'] = ports
+
+ return super(NetworkScenarioTest, self).create_server(
+ name=name, image=image, flavor=flavor,
+ wait_on_boot=wait_on_boot, wait_on_delete=wait_on_delete,
+ create_kwargs=create_kwargs)
+
# power/provision states as of icehouse
class BaremetalPowerStates(object):
@@ -1124,7 +1191,7 @@
node = None
try:
node = self.get_node(instance_id=instance_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
return node is not None
@@ -1187,7 +1254,7 @@
self.servers_client.wait_for_server_status(self.instance['id'],
'ACTIVE')
self.node = self.get_node(instance_id=self.instance['id'])
- _, self.instance = self.servers_client.get_server(self.instance['id'])
+ self.instance = self.servers_client.get_server(self.instance['id'])
def terminate_instance(self):
self.servers_client.delete_server(self.instance['id'])
@@ -1259,8 +1326,9 @@
@classmethod
def credentials(cls):
- admin_creds = auth.get_default_credentials('identity_admin')
- creds = auth.get_default_credentials('user')
+ admin_creds = cred_provider.get_configured_credentials(
+ 'identity_admin')
+ creds = cred_provider.get_configured_credentials('user')
admin_creds.tenant_name = creds.tenant_name
return admin_creds
diff --git a/tempest/scenario/orchestration/test_server_cfn_init.py b/tempest/scenario/orchestration/test_server_cfn_init.py
index 6052e0b..53f7843 100644
--- a/tempest/scenario/orchestration/test_server_cfn_init.py
+++ b/tempest/scenario/orchestration/test_server_cfn_init.py
@@ -81,7 +81,7 @@
server_resource = self.client.get_resource(sid, 'SmokeServer')
server_id = server_resource['physical_resource_id']
- _, server = self.servers_client.get_server(server_id)
+ server = self.servers_client.get_server(server_id)
server_ip =\
server['addresses'][CONF.compute.network_for_ssh][0]['addr']
@@ -126,6 +126,7 @@
@test.attr(type='slow')
@decorators.skip_because(bug='1374175')
+ @test.idempotent_id('2be9be1f-8106-4ee2-a7ba-444c7557db2f')
@test.services('orchestration', 'compute')
def test_server_cfn_init(self):
self.assign_keypair()
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 469ac4a..ff450de 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -96,6 +96,7 @@
self.assertEqual(aggregate['availability_zone'], availability_zone)
return aggregate
+ @test.idempotent_id('cb2b4c4f-0c7c-4164-bdde-6285b302a081')
@test.services('compute')
def test_aggregate_basic_ops(self):
self.useFixture(fixtures.LockFixture('availability_zone'))
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index fd4449a..434d3df 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -104,7 +104,7 @@
return int(ephemeral)
def add_floating_ip(self):
- _, floating_ip = self.floating_ips_client.create_floating_ip()
+ floating_ip = self.floating_ips_client.create_floating_ip()
self.floating_ips_client.associate_floating_ip_to_server(
floating_ip['ip'], self.instance['id'])
return floating_ip['ip']
@@ -117,6 +117,7 @@
self.assertEqual(n_port['device_id'], self.instance['id'])
self.assertEqual(n_port['mac_address'], port['address'])
+ @test.idempotent_id('549173a5-38ec-42bb-b0e2-c8b9f4a08943')
@test.services('baremetal', 'compute', 'image', 'network')
def test_baremetal_server_ops(self):
test_filename = '/mnt/rebuild_test.txt'
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index 35f6689..4c4dc94 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -65,7 +65,7 @@
def check_login_page(self):
response = urllib2.urlopen(CONF.dashboard.dashboard_url)
- self.assertIn("Log In", response.read())
+ self.assertIn("id_username", response.read())
def user_login(self, username, password):
self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
@@ -89,6 +89,7 @@
response = self.opener.open(CONF.dashboard.dashboard_url)
self.assertIn('Overview', response.read())
+ @test.idempotent_id('4f8851b1-0e69-482b-b63b-84c6e76f6c80')
@test.services('dashboard')
def test_basic_scenario(self):
creds = self.credentials()
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index ac2ef8a..eed3d0b 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -48,6 +48,7 @@
self.nova_volume_attach()
self.nova_volume_detach()
+ @test.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
@test.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_luks(self):
self.launch_instance()
@@ -55,9 +56,10 @@
'luks.LuksEncryptor')
self.attach_detach_volume()
+ @test.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
@test.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_cryptsetup(self):
self.launch_instance()
self.create_encrypted_volume('nova.volume.encryptors.'
'cryptsetup.CryptsetupEncryptor')
- self.attach_detach_volume()
\ No newline at end of file
+ self.attach_detach_volume()
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 99a2023..af2b4cb 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -12,7 +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.
-from tempest_lib import exceptions
+from tempest_lib import exceptions as lib_exc
from tempest.common.utils import data_utils
from tempest import config
@@ -54,7 +54,7 @@
function, args, kwargs = cls._cleanup_resources.pop(-1)
try:
function(*args, **kwargs)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
super(TestLargeOpsScenario, cls).resource_cleanup()
@@ -87,7 +87,7 @@
security_groups=[{'name': secgroup['name']}])
# needed because of bug 1199788
params = {'name': name}
- _, server_list = self.servers_client.list_servers(params)
+ server_list = self.servers_client.list_servers(params)
self.servers = server_list['servers']
for server in self.servers:
# after deleting all servers - wait for all servers to clear
@@ -104,14 +104,17 @@
self.glance_image_create()
self.nova_boot()
+ @test.idempotent_id('14ba0e78-2ed9-4d17-9659-a48f4756ecb3')
@test.services('compute', 'image')
def test_large_ops_scenario_1(self):
self._large_ops_scenario()
+ @test.idempotent_id('b9b79b88-32aa-42db-8f8f-dcc8f4b4ccfe')
@test.services('compute', 'image')
def test_large_ops_scenario_2(self):
self._large_ops_scenario()
+ @test.idempotent_id('3aab7e82-2de3-419a-9da1-9f3a070668fb')
@test.services('compute', 'image')
def test_large_ops_scenario_3(self):
self._large_ops_scenario()
diff --git a/tempest/scenario/test_load_balancer_basic.py b/tempest/scenario/test_load_balancer_basic.py
index 57a5406..6f6036f 100644
--- a/tempest/scenario/test_load_balancer_basic.py
+++ b/tempest/scenario/test_load_balancer_basic.py
@@ -161,7 +161,7 @@
"""
for server_id, ip in self.server_ips.iteritems():
private_key = self.servers_keypairs[server_id]['private_key']
- server_name = self.servers_client.get_server(server_id)[1]['name']
+ server_name = self.servers_client.get_server(server_id)['name']
username = config.scenario.ssh_user
ssh_client = self.get_remote_client(
server_or_ip=ip,
@@ -185,7 +185,7 @@
# Start netcat
start_server = ('while true; do '
- 'sudo nc -l -p %(port)s -e sh /tmp/%(script)s; '
+ 'sudo nc -ll -p %(port)s -e sh /tmp/%(script)s; '
'done &')
cmd = start_server % {'port': self.port1,
'script': 'script1'}
@@ -309,6 +309,7 @@
for member, counter in counters.iteritems():
self.assertGreater(counter, 0, 'Member %s never balanced' % member)
+ @test.idempotent_id('c0c6f1ca-603b-4509-9c0f-2c63f0d838ee')
@test.services('compute', 'network')
def test_load_balancer_basic(self):
self._create_server('server1')
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 5ea48e0..63f74c4 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -53,13 +53,13 @@
create_kwargs=create_kwargs)
def nova_list(self):
- _, servers = self.servers_client.list_servers()
+ servers = self.servers_client.list_servers()
# The list servers in the compute client is inconsistent...
servers = servers['servers']
self.assertIn(self.server['id'], [x['id'] for x in servers])
def nova_show(self):
- _, got_server = self.servers_client.get_server(self.server['id'])
+ got_server = self.servers_client.get_server(self.server['id'])
self.assertThat(
self.server, custom_matchers.MatchesDictExceptForKeys(
got_server, excluded_keys=['OS-EXT-AZ:availability_zone']))
@@ -78,7 +78,7 @@
def nova_volume_attach(self):
volume_device_path = '/dev/' + CONF.compute.volume_device_name
volume = self.servers_client.attach_volume(
- self.server['id'], self.volume['id'], volume_device_path)[1]
+ self.server['id'], self.volume['id'], volume_device_path)
self.assertEqual(self.volume['id'], volume['id'])
self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
# Refresh the volume after the attachment
@@ -109,7 +109,7 @@
self.server['id'], secgroup['name'])
def wait_for_secgroup_add():
- _, body = self.servers_client.get_server(self.server['id'])
+ body = self.servers_client.get_server(self.server['id'])
return {'name': secgroup['name']} in body['security_groups']
if not test.call_until_true(wait_for_secgroup_add,
@@ -119,6 +119,7 @@
'%s' % (secgroup['id'], self.server['id']))
raise exceptions.TimeoutException(msg)
+ @test.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
@test.services('compute', 'volume', 'image', 'network')
def test_minimum_basic_scenario(self):
self.glance_image_create()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 598c6d1..6e82a41 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -94,6 +94,7 @@
self._check_network_connectivity()
@decorators.skip_because(bug="1323658")
+ @test.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
@test.services('compute', 'network')
def test_server_connectivity_stop_start(self):
self._setup_network_and_servers()
@@ -104,12 +105,14 @@
self.servers_client.start(self.server['id'])
self._wait_server_status_and_check_network_connectivity()
+ @test.idempotent_id('7b6860c2-afa3-4846-9522-adeb38dfbe08')
@test.services('compute', 'network')
def test_server_connectivity_reboot(self):
self._setup_network_and_servers()
self.servers_client.reboot(self.server['id'], reboot_type='SOFT')
self._wait_server_status_and_check_network_connectivity()
+ @test.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
@test.services('compute', 'network')
def test_server_connectivity_rebuild(self):
self._setup_network_and_servers()
@@ -118,6 +121,7 @@
image_ref=image_ref_alt)
self._wait_server_status_and_check_network_connectivity()
+ @test.idempotent_id('2b2642db-6568-4b35-b812-eceed3fa20ce')
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
@test.services('compute', 'network')
@@ -129,6 +133,7 @@
self.servers_client.unpause_server(self.server['id'])
self._wait_server_status_and_check_network_connectivity()
+ @test.idempotent_id('5cdf9499-541d-4923-804e-b9a60620a7f0')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.services('compute', 'network')
@@ -142,6 +147,7 @@
self._wait_server_status_and_check_network_connectivity()
@decorators.skip_because(bug="1323658")
+ @test.idempotent_id('719eb59d-2f42-4b66-b8b1-bb1254473967')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
@test.services('compute', 'network')
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index fc174cd..4199b2c 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -16,7 +16,6 @@
import collections
import re
-from tempest_lib import decorators
import testtools
from tempest.common.utils import data_utils
@@ -230,7 +229,7 @@
port_list = self._list_ports(device_id=server['id'])
self.assertEqual(1, len(port_list))
old_port = port_list[0]
- _, interface = self.interface_client.create_interface(
+ interface = self.interface_client.create_interface(
server=server['id'],
network_id=self.new_net.id)
self.addCleanup(self.network_client.wait_for_resource_deletion,
@@ -243,7 +242,7 @@
def check_ports():
self.new_port_list = [port for port in
self._list_ports(device_id=server['id'])
- if port != old_port]
+ if port['id'] != old_port['id']]
return len(self.new_port_list) == 1
if not test.call_until_true(check_ports, CONF.network.build_timeout,
@@ -329,6 +328,7 @@
raise
@test.attr(type='smoke')
+ @test.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
@test.services('compute', 'network')
def test_network_basic_ops(self):
"""
@@ -379,8 +379,12 @@
msg="after re-associate "
"floating ip")
+ @test.idempotent_id('c5adff73-e961-41f1-b4a9-343614f18cfa')
@testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
'NIC hotplug not available')
+ @testtools.skipIf(CONF.network.port_vnic_type in ['direct', 'macvtap'],
+ 'NIC hotplug not supported for '
+ 'vnic_type direct or macvtap')
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_hotplug_nic(self):
@@ -398,6 +402,7 @@
self._hotplug_server()
self._check_network_internal_connectivity(network=self.new_net)
+ @test.idempotent_id('04b9fe4e-85e8-4aea-b937-ea93885ac59f')
@testtools.skipIf(CONF.baremetal.driver_enabled,
'Router state cannot be altered on a shared baremetal '
'network')
@@ -429,24 +434,16 @@
should_connect=True, msg="after updating "
"admin_state_up of router to True")
- def _check_dns_server(self, ssh_client, dns_servers):
- servers = ssh_client.get_dns_servers()
- self.assertEqual(set(dns_servers), set(servers),
- 'Looking for servers: {trgt_serv}. '
- 'Retrieved DNS nameservers: {act_serv} '
- 'From host: {host}.'
- .format(host=ssh_client.ssh_client.host,
- act_serv=servers,
- trgt_serv=dns_servers))
-
- @decorators.skip_because(bug="1412325")
+ @test.idempotent_id('d8bb918e-e2df-48b2-97cd-b73c95450980')
+ @testtools.skipIf(CONF.baremetal.driver_enabled,
+ 'network isolation not available for baremetal nodes')
@testtools.skipUnless(CONF.scenario.dhcp_client,
"DHCP client is not available.")
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_subnet_details(self):
"""Tests that subnet's extra configuration details are affecting
- the VMs
+ the VMs. This test relies on non-shared, isolated tenant networks.
NOTE: Neutron subnets push data to servers via dhcp-agent, so any
update in subnet requires server to actively renew its DHCP lease.
@@ -469,6 +466,13 @@
# arbitrary ip addresses as nameservers, instead of parsing CONF
initial_dns_server = '1.2.3.4'
alt_dns_server = '9.8.7.6'
+
+ # renewal should be immediate.
+ # Timeouts are suggested by salvatore-orlando in
+ # https://bugs.launchpad.net/neutron/+bug/1412325/comments/3
+ renew_delay = CONF.network.build_interval
+ renew_timeout = CONF.network.build_timeout
+
self._setup_network_and_servers(dns_nameservers=[initial_dns_server])
self.check_public_network_connectivity(should_connect=True)
@@ -477,18 +481,44 @@
private_key = self._get_server_key(server)
ssh_client = self._ssh_to_server(ip_address, private_key)
- self._check_dns_server(ssh_client, [initial_dns_server])
+ dns_servers = [initial_dns_server]
+ servers = ssh_client.get_dns_servers()
+ self.assertEqual(set(dns_servers), set(servers),
+ 'Looking for servers: {trgt_serv}. '
+ 'Retrieved DNS nameservers: {act_serv} '
+ 'From host: {host}.'
+ .format(host=ssh_client.ssh_client.host,
+ act_serv=servers,
+ trgt_serv=dns_servers))
self.subnet.update(dns_nameservers=[alt_dns_server])
# asserts that Neutron DB has updated the nameservers
self.assertEqual([alt_dns_server], self.subnet.dns_nameservers,
"Failed to update subnet's nameservers")
- # server needs to renew its dhcp lease in order to get the new dns
- # definitions from subnet
- ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
- self._check_dns_server(ssh_client, [alt_dns_server])
+ def check_new_dns_server():
+ """Server needs to renew its dhcp lease in order to get the new dns
+ definitions from subnet
+ NOTE(amuller): we are renewing the lease as part of the retry
+ because Neutron updates dnsmasq asynchronously after the
+ subnet-update API call returns.
+ """
+ ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
+ if ssh_client.get_dns_servers() != [alt_dns_server]:
+ LOG.debug("Failed to update DNS nameservers")
+ return False
+ return True
+ self.assertTrue(test.call_until_true(check_new_dns_server,
+ renew_timeout,
+ renew_delay),
+ msg="DHCP renewal failed to fetch "
+ "new DNS nameservers")
+
+ @test.idempotent_id('f5dfcc22-45fd-409f-954c-5bd500d7890b')
+ @testtools.skipIf(CONF.baremetal.driver_enabled,
+ 'admin_state of instance ports cannot be altered '
+ 'for baremetal nodes')
@test.attr(type='smoke')
@test.services('compute', 'network')
def test_update_instance_port_admin_state(self):
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index dc82217..d5d2d77 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.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 functools
import netaddr
from tempest import config
from tempest.openstack.common import log as logging
@@ -118,14 +119,28 @@
ssh1, srv1 = self.prepare_server()
ssh2, srv2 = self.prepare_server()
+ def guest_has_address(ssh, addr):
+ return addr in ssh.get_ip_list()
+
+ srv1_v6_addr_assigned = functools.partial(
+ guest_has_address, ssh1, srv1['accessIPv6'])
+ srv2_v6_addr_assigned = functools.partial(
+ guest_has_address, ssh2, srv2['accessIPv6'])
+
result = ssh1.get_ip_list()
self.assertIn(srv1['accessIPv4'], result)
# v6 should be configured since the image supports it
- self.assertIn(srv1['accessIPv6'], result)
+ # It can take time for ipv6 automatic address to get assigned
+ self.assertTrue(
+ test.call_until_true(srv1_v6_addr_assigned,
+ CONF.compute.ping_timeout, 1))
result = ssh2.get_ip_list()
self.assertIn(srv2['accessIPv4'], result)
# v6 should be configured since the image supports it
- self.assertIn(srv2['accessIPv6'], result)
+ # It can take time for ipv6 automatic address to get assigned
+ self.assertTrue(
+ test.call_until_true(srv2_v6_addr_assigned,
+ CONF.compute.ping_timeout, 1))
result = ssh1.ping_host(srv2['accessIPv4'])
self.assertIn('0% packet loss', result)
result = ssh2.ping_host(srv1['accessIPv4'])
@@ -142,10 +157,12 @@
else:
LOG.warning('Ping6 is not available, skipping')
+ @test.idempotent_id('2c92df61-29f0-4eaa-bee3-7c65bef62a43')
@test.services('compute', 'network')
def test_slaac_from_os(self):
self._prepare_and_test(address6_mode='slaac')
+ @test.idempotent_id('d7e1f858-187c-45a6-89c9-bdafde619a9f')
@test.services('compute', 'network')
def test_dhcp6_stateless_from_os(self):
self._prepare_and_test(address6_mode='dhcpv6-stateless')
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 83739fd..4fbadb0 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -76,6 +76,8 @@
* test that traffic is blocked with default security group
* test that traffic is enabled after updating port with new security
group having appropriate rule
+ 8. _test_multiple_security_groups: test multiple security groups can be
+ associated with the vm
assumptions:
1. alt_tenant/user existed and is different from primary_tenant/user
@@ -89,7 +91,7 @@
its own router connected to the public network
"""
- class TenantProperties():
+ class TenantProperties(object):
"""
helper class to save tenant details
id
@@ -238,7 +240,8 @@
],
'key_name': tenant.keypair['name'],
'security_groups': security_groups_names,
- 'tenant_id': tenant.creds.tenant_id
+ 'tenant_id': tenant.creds.tenant_id,
+ 'network_client': tenant.manager.network_client
}
server = self.create_server(name=name, create_kwargs=create_kwargs)
self.assertEqual(
@@ -427,6 +430,7 @@
self.assertIn((subnet_id, server_ip, mac_addr), port_detail_list)
@test.attr(type='smoke')
+ @test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
@test.services('compute', 'network')
def test_cross_tenant_traffic(self):
if not self.isolated_creds.is_multi_tenant():
@@ -448,6 +452,7 @@
raise
@test.attr(type='smoke')
+ @test.idempotent_id('63163892-bbf6-4249-aa12-d5ea1f8f421b')
@test.services('compute', 'network')
def test_in_tenant_traffic(self):
try:
@@ -462,6 +467,7 @@
raise
@test.attr(type='smoke')
+ @test.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
@test.services('compute', 'network')
def test_port_update_new_security_group(self):
"""
@@ -511,3 +517,38 @@
for tenant in self.tenants.values():
self._log_console_output(servers=tenant.servers)
raise
+
+ @test.attr(type='smoke')
+ @test.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
+ @test.services('compute', 'network')
+ def test_multiple_security_groups(self):
+ """
+ This test verifies multiple security groups and checks that rules
+ provided in the both the groups is applied onto VM
+ """
+ tenant = self.primary_tenant
+ ip = self._get_server_ip(tenant.access_point,
+ floating=self.floating_ip_access)
+ ssh_login = CONF.compute.image_ssh_user
+ private_key = tenant.keypair['private_key']
+ self.check_vm_connectivity(ip,
+ should_connect=False)
+ ruleset = dict(
+ protocol='icmp',
+ direction='ingress'
+ )
+ self._create_security_group_rule(
+ secgroup=tenant.security_groups['default'],
+ **ruleset
+ )
+ """
+ Vm now has 2 security groups one with ssh rule(
+ already added in setUp() method),and other with icmp rule
+ (added in the above step).The check_vm_connectivity tests
+ -that vm ping test is successful
+ -ssh to vm is successful
+ """
+ self.check_vm_connectivity(ip,
+ username=ssh_login,
+ private_key=private_key,
+ should_connect=True)
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index d10fcce..d0b595a 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -42,6 +42,7 @@
cls.set_network_resources()
super(TestServerAdvancedOps, cls).resource_setup()
+ @test.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
@test.services('compute')
@@ -62,6 +63,7 @@
self.servers_client.wait_for_server_status(instance_id,
'ACTIVE')
+ @test.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
@test.services('compute')
@@ -74,19 +76,19 @@
self.servers_client.suspend_server(instance_id)
self.servers_client.wait_for_server_status(instance_id,
'SUSPENDED')
- _, fetched_instance = self.servers_client.get_server(instance_id)
+ fetched_instance = self.servers_client.get_server(instance_id)
LOG.debug("Resuming instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.resume_server(instance_id)
self.servers_client.wait_for_server_status(instance_id,
'ACTIVE')
- _, fetched_instance = self.servers_client.get_server(instance_id)
+ fetched_instance = self.servers_client.get_server(instance_id)
LOG.debug("Suspending instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.suspend_server(instance_id)
self.servers_client.wait_for_server_status(instance_id,
'SUSPENDED')
- _, fetched_instance = self.servers_client.get_server(instance_id)
+ fetched_instance = self.servers_client.get_server(instance_id)
LOG.debug("Resuming instance %s. Current status: %s",
instance_id, fetched_instance['status'])
self.servers_client.resume_server(instance_id)
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 23743c5..b306b11 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -80,7 +80,7 @@
def verify_ssh(self):
if self.run_ssh:
# Obtain a floating IP
- _, floating_ip = self.floating_ips_client.create_floating_ip()
+ floating_ip = self.floating_ips_client.create_floating_ip()
self.addCleanup(self.delete_wrapper,
self.floating_ips_client.delete_floating_ip,
floating_ip['id'])
@@ -93,6 +93,7 @@
username=self.image_utils.ssh_user(self.image_ref),
private_key=self.keypair['private_key'])
+ @test.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
@test.services('compute', 'network')
def test_server_basicops(self):
self.add_keypair()
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 8882177..155ecbf 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -60,6 +60,7 @@
self.servers_client.unshelve_server(server['id'])
self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+ @test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
@testtools.skipUnless(CONF.compute_feature_enabled.shelve,
'Shelve is not available.')
@test.services('compute', 'network', 'image')
@@ -77,7 +78,7 @@
create_kwargs=create_kwargs)
if CONF.compute.use_floatingip_for_ssh:
- _, floating_ip = self.floating_ips_client.create_floating_ip()
+ floating_ip = self.floating_ips_client.create_floating_ip()
self.addCleanup(self.delete_wrapper,
self.floating_ips_client.delete_floating_ip,
floating_ip['id'])
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 5cb7c99..109d36b 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -57,6 +57,7 @@
got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
self.assertEqual(self.timestamp, got_timestamp)
+ @test.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@test.services('compute', 'network', 'image')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 16f5283..bd3cefa 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -16,6 +16,7 @@
import time
from tempest_lib import decorators
+from tempest_lib import exceptions as lib_exc
import testtools
from tempest.common.utils import data_utils
@@ -23,6 +24,7 @@
from tempest import exceptions
from tempest.openstack.common import log as logging
from tempest.scenario import manager
+from tempest import test
import tempest.test
CONF = config.CONF
@@ -85,7 +87,7 @@
try:
while self.snapshots_client.get_snapshot(snapshot['id']):
time.sleep(1)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
pass
self.addCleanup(cleaner)
self._wait_for_volume_status(volume, 'available')
@@ -102,7 +104,7 @@
def _attach_volume(self, server, volume):
# TODO(andreaf) we should use device from config instead if vdb
- _, attached_volume = self.servers_client.attach_volume(
+ attached_volume = self.servers_client.attach_volume(
server['id'], volume['id'], device='/dev/vdb')
self.assertEqual(volume['id'], attached_volume['id'])
self._wait_for_volume_status(attached_volume, 'in-use')
@@ -139,6 +141,7 @@
self.assertEqual(self.timestamp, got_timestamp)
@decorators.skip_because(bug="1205344")
+ @test.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting is not available.')
@tempest.test.services('compute', 'network', 'volume', 'image')
diff --git a/tempest/scenario/test_swift_basic_ops.py b/tempest/scenario/test_swift_basic_ops.py
index 660b586..b622c4a 100644
--- a/tempest/scenario/test_swift_basic_ops.py
+++ b/tempest/scenario/test_swift_basic_ops.py
@@ -38,6 +38,7 @@
* change ACL of the container and make sure it works successfully
"""
+ @test.idempotent_id('b920faf1-7b8a-4657-b9fe-9c4512bfb381')
@test.services('object_storage')
def test_swift_basic_ops(self):
self.get_swift_stat()
@@ -51,6 +52,7 @@
not_present_obj=[obj_name])
self.delete_container(container_name)
+ @test.idempotent_id('916c7111-cb1f-44b2-816d-8f760e4ea910')
@test.services('object_storage')
def test_swift_acl_anonymous_download(self):
"""This test will cover below steps:
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
index dce6023..8305641 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -1,7 +1,5 @@
-#
# Copyright 2014 Red Hat
#
-# Author: Chris Dent <chdent@redhat.com>
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -76,19 +74,22 @@
LOG.debug('got samples %s', results)
# Extract container info from samples.
- containers = [sample['resource_metadata']['container']
- for sample in results
- if sample['resource_metadata']['container']
- != 'None']
- # Extract object info from samples.
- objects = [sample['resource_metadata']['object']
- for sample in results
- if sample['resource_metadata']['object'] != 'None']
+ containers, objects = [], []
+ for sample in results:
+ meta = sample['resource_metadata']
+ if meta.get('container') and meta['container'] != 'None':
+ containers.append(meta['container'])
+ elif (meta.get('target') and
+ meta['target']['metadata']['container'] != 'None'):
+ containers.append(meta['target']['metadata']['container'])
- return (containers
- and objects
- and container_name in containers
- and obj_name in objects)
+ if meta.get('object') and meta['object'] != 'None':
+ objects.append(meta['object'])
+ elif (meta.get('target') and
+ meta['target']['metadata']['object'] != 'None'):
+ objects.append(meta['target']['metadata']['object'])
+
+ return (container_name in containers and obj_name in objects)
self.assertTrue(test.call_until_true(_check_samples,
NOTIFICATIONS_WAIT,
@@ -96,6 +97,7 @@
'Correct notifications were not received after '
'%s seconds.' % NOTIFICATIONS_WAIT)
+ @test.idempotent_id('6d6b88e5-3e38-41bc-b34a-79f713a6cb84')
@test.services('object_storage', 'telemetry')
def test_swift_middleware_notifies(self):
container_name = self.create_container()
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index c8f438e..d1ea270 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -101,7 +101,7 @@
def _ssh_to_server(self, server, keypair):
if CONF.compute.use_floatingip_for_ssh:
- _, floating_ip = self.floating_ips_client.create_floating_ip()
+ floating_ip = self.floating_ips_client.create_floating_ip()
self.addCleanup(self.delete_wrapper,
self.floating_ips_client.delete_floating_ip,
floating_ip['id'])
@@ -133,6 +133,7 @@
self.assertEqual(expected, actual)
@decorators.skip_because(bug='1373513')
+ @test.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
@test.services('compute', 'volume', 'image')
def test_volume_boot_pattern(self):
keypair = self.create_keypair()
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index f997a65..68ec6e7 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -21,8 +21,8 @@
import testscenarios
import testtools
-from tempest import auth
from tempest import clients
+from tempest.common import cred_provider
from tempest.common.utils import misc
from tempest import config
from tempest import exceptions
@@ -101,7 +101,7 @@
def __init__(self):
os = clients.Manager(
- auth.get_default_credentials('user', fill_in=False))
+ cred_provider.get_configured_credentials('user', fill_in=False))
self.images_client = os.images_client
self.flavors_client = os.flavors_client
self.image_pattern = CONF.input_scenario.image_regex
@@ -120,12 +120,15 @@
if not CONF.service_available.glance:
return []
if not hasattr(self, '_scenario_images'):
- images = self.images_client.list_images()
- self._scenario_images = [
- (self._normalize_name(i['name']), dict(image_ref=i['id']))
- for i in images if re.search(self.image_pattern,
- str(i['name']))
- ]
+ try:
+ images = self.images_client.list_images()
+ self._scenario_images = [
+ (self._normalize_name(i['name']), dict(image_ref=i['id']))
+ for i in images if re.search(self.image_pattern,
+ str(i['name']))
+ ]
+ except Exception:
+ self._scenario_images = []
return self._scenario_images
@property
@@ -134,12 +137,15 @@
:return: a scenario with name and uuid of flavors
"""
if not hasattr(self, '_scenario_flavors'):
- flavors = self.flavors_client.list_flavors()
- self._scenario_flavors = [
- (self._normalize_name(f['name']), dict(flavor_ref=f['id']))
- for f in flavors if re.search(self.flavor_pattern,
- str(f['name']))
- ]
+ try:
+ flavors = self.flavors_client.list_flavors()
+ self._scenario_flavors = [
+ (self._normalize_name(f['name']), dict(flavor_ref=f['id']))
+ for f in flavors if re.search(self.flavor_pattern,
+ str(f['name']))
+ ]
+ except Exception:
+ self._scenario_flavors = []
return self._scenario_flavors
diff --git a/tempest/services/baremetal/v1/json/baremetal_client.py b/tempest/services/baremetal/v1/json/baremetal_client.py
index 1c72a2b..09b6cd1 100644
--- a/tempest/services/baremetal/v1/json/baremetal_client.py
+++ b/tempest/services/baremetal/v1/json/baremetal_client.py
@@ -136,18 +136,18 @@
Create a baremetal node with the specified parameters.
:param cpu_arch: CPU architecture of the node. Default: x86_64.
- :param cpu_num: Number of CPUs. Default: 8.
- :param storage: Disk size. Default: 1024.
- :param memory: Available RAM. Default: 4096.
+ :param cpus: Number of CPUs. Default: 8.
+ :param local_gb: Disk size. Default: 1024.
+ :param memory_mb: Available RAM. Default: 4096.
:param driver: Driver name. Default: "fake"
:return: A tuple with the server response and the created node.
"""
node = {'chassis_uuid': chassis_id,
'properties': {'cpu_arch': kwargs.get('cpu_arch', 'x86_64'),
- 'cpu_num': kwargs.get('cpu_num', 8),
- 'storage': kwargs.get('storage', 1024),
- 'memory': kwargs.get('memory', 4096)},
+ 'cpus': kwargs.get('cpus', 8),
+ 'local_gb': kwargs.get('local_gb', 1024),
+ 'memory_mb': kwargs.get('memory_mb', 4096)},
'driver': kwargs.get('driver', 'fake')}
return self._create_request('nodes', node)
@@ -232,9 +232,9 @@
"""
node_attributes = ('properties/cpu_arch',
- 'properties/cpu_num',
- 'properties/storage',
- 'properties/memory',
+ 'properties/cpus',
+ 'properties/local_gb',
+ 'properties/memory_mb',
'driver',
'instance_uuid')
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index f581e89..1cbdb0c 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -15,6 +15,7 @@
import ConfigParser
import contextlib
+from tempest_lib import exceptions as lib_exc
import types
import urlparse
@@ -38,7 +39,7 @@
# FIXME(andreaf) replace credentials and auth_url with auth_provider
insecure_ssl = CONF.identity.disable_ssl_certificate_validation
- ca_cert = CONF.identity.ca_certificates_file
+ self.ca_cert = CONF.identity.ca_certificates_file
self.connection_timeout = str(CONF.boto.http_socket_timeout)
self.num_retries = str(CONF.boto.num_retries)
@@ -48,7 +49,7 @@
"auth_url": auth_url,
"tenant_name": tenant_name,
"insecure": insecure_ssl,
- "cacert": ca_cert}
+ "cacert": self.ca_cert}
def _keystone_aws_get(self):
# FIXME(andreaf) Move EC2 credentials to AuthProvider
@@ -65,7 +66,7 @@
ec2_cred = keystone.ec2.create(keystone.auth_user_id,
keystone.auth_tenant_id)
if not all((ec2_cred, ec2_cred.access, ec2_cred.secret)):
- raise exceptions.NotFound("Unable to get access and secret keys")
+ raise lib_exc.NotFound("Unable to get access and secret keys")
return ec2_cred
def _config_boto_timeout(self, timeout, retries):
@@ -76,6 +77,16 @@
boto.config.set("Boto", "http_socket_timeout", timeout)
boto.config.set("Boto", "num_retries", retries)
+ def _config_boto_ca_certificates_file(self, ca_cert):
+ if ca_cert is None:
+ return
+
+ try:
+ boto.config.add_section("Boto")
+ except ConfigParser.DuplicateSectionError:
+ pass
+ boto.config.set("Boto", "ca_certificates_file", ca_cert)
+
def __getattr__(self, name):
"""Automatically creates methods for the allowed methods set."""
if name in self.ALLOWED_METHODS:
@@ -93,6 +104,7 @@
def get_connection(self):
self._config_boto_timeout(self.connection_timeout, self.num_retries)
+ self._config_boto_ca_certificates_file(self.ca_cert)
if not all((self.connection_data["aws_access_key_id"],
self.connection_data["aws_secret_access_key"])):
if all([self.ks_cred.get('auth_url'),
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index 94ea713..10955fd 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -15,10 +15,11 @@
import json
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute import aggregates as schema
from tempest.api_schema.response.compute.v2 import aggregates as v2_schema
from tempest.common import service_client
-from tempest import exceptions
class AggregatesClientJSON(service_client.ServiceClient):
@@ -68,7 +69,7 @@
def is_resource_deleted(self, id):
try:
self.get_aggregate(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/compute/json/availability_zone_client.py b/tempest/services/compute/json/availability_zone_client.py
index e37c9d9..343c412 100644
--- a/tempest/services/compute/json/availability_zone_client.py
+++ b/tempest/services/compute/json/availability_zone_client.py
@@ -25,11 +25,13 @@
resp, body = self.get('os-availability-zone')
body = json.loads(body)
self.validate_response(schema.get_availability_zone_list, resp, body)
- return resp, body['availabilityZoneInfo']
+ return service_client.ResponseBodyList(resp,
+ body['availabilityZoneInfo'])
def get_availability_zone_list_detail(self):
resp, body = self.get('os-availability-zone/detail')
body = json.loads(body)
self.validate_response(schema.get_availability_zone_list_detail, resp,
body)
- return resp, body['availabilityZoneInfo']
+ return service_client.ResponseBodyList(resp,
+ body['availabilityZoneInfo'])
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
new file mode 100644
index 0000000..d8bbadd
--- /dev/null
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -0,0 +1,43 @@
+# 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.
+
+import json
+import urllib
+
+from tempest.api_schema.response.compute import baremetal_nodes as schema
+from tempest.common import service_client
+
+
+class BaremetalNodesClientJSON(service_client.ServiceClient):
+ """
+ Tests Baremetal API
+ """
+
+ def list_baremetal_nodes(self, params=None):
+ """List all baremetal nodes."""
+ url = 'os-baremetal-nodes'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(schema.list_baremetal_nodes, resp, body)
+ return service_client.ResponseBodyList(resp, body['nodes'])
+
+ def get_baremetal_node(self, baremetal_node_id):
+ """Returns the details of a single baremetal node."""
+ url = 'os-baremetal-nodes/%s' % baremetal_node_id
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(schema.get_baremetal_node, resp, body)
+ return service_client.ResponseBody(resp, body['node'])
diff --git a/tempest/services/compute/json/certificates_client.py b/tempest/services/compute/json/certificates_client.py
index b705c37..4a30f1e 100644
--- a/tempest/services/compute/json/certificates_client.py
+++ b/tempest/services/compute/json/certificates_client.py
@@ -27,7 +27,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.get_certificate, resp, body)
- return resp, body['certificate']
+ return service_client.ResponseBody(resp, body['certificate'])
def create_certificate(self):
"""create certificates."""
@@ -35,4 +35,4 @@
resp, body = self.post(url, None)
body = json.loads(body)
self.validate_response(v2schema.create_certificate, resp, body)
- return resp, body['certificate']
+ return service_client.ResponseBody(resp, body['certificate'])
diff --git a/tempest/services/compute/json/extensions_client.py b/tempest/services/compute/json/extensions_client.py
index d3148b4..09561b3 100644
--- a/tempest/services/compute/json/extensions_client.py
+++ b/tempest/services/compute/json/extensions_client.py
@@ -26,14 +26,14 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_extensions, resp, body)
- return resp, body['extensions']
+ return service_client.ResponseBodyList(resp, body['extensions'])
def is_enabled(self, extension):
- _, extensions = self.list_extensions()
+ extensions = self.list_extensions()
exts = extensions['extensions']
return any([e for e in exts if e['name'] == extension])
def get_extension(self, extension_alias):
resp, body = self.get('extensions/%s' % extension_alias)
body = json.loads(body)
- return resp, body['extension']
+ return service_client.ResponseBody(resp, body['extension'])
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 5797c16..31cf5b2 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -26,11 +26,11 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.fixed_ips, resp, body)
- return resp, body['fixed_ip']
+ return service_client.ResponseBody(resp, body['fixed_ip'])
def reserve_fixed_ip(self, ip, body):
"""This reserves and unreserves fixed ips."""
url = "os-fixed-ips/%s/action" % (ip)
resp, body = self.post(url, json.dumps(body))
self.validate_response(schema.fixed_ip_action, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp)
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 9c586e3..0354ba4 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -16,9 +16,10 @@
import json
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute.v2 import floating_ips as schema
from tempest.common import service_client
-from tempest import exceptions
class FloatingIPsClientJSON(service_client.ServiceClient):
@@ -32,17 +33,15 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_floating_ips, resp, body)
- return resp, body['floating_ips']
+ return service_client.ResponseBodyList(resp, body['floating_ips'])
def get_floating_ip_details(self, floating_ip_id):
"""Get the details of a floating IP."""
url = "os-floating-ips/%s" % str(floating_ip_id)
resp, body = self.get(url)
body = json.loads(body)
- if resp.status == 404:
- raise exceptions.NotFound(body)
self.validate_response(schema.floating_ip, resp, body)
- return resp, body['floating_ip']
+ return service_client.ResponseBody(resp, body['floating_ip'])
def create_floating_ip(self, pool_name=None):
"""Allocate a floating IP to the project."""
@@ -52,14 +51,14 @@
resp, body = self.post(url, post_body)
body = json.loads(body)
self.validate_response(schema.floating_ip, resp, body)
- return resp, body['floating_ip']
+ return service_client.ResponseBody(resp, body['floating_ip'])
def delete_floating_ip(self, floating_ip_id):
"""Deletes the provided floating IP from the project."""
url = "os-floating-ips/%s" % str(floating_ip_id)
resp, body = self.delete(url)
self.validate_response(schema.add_remove_floating_ip, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def associate_floating_ip_to_server(self, floating_ip, server_id):
"""Associate the provided floating IP to a specific server."""
@@ -73,7 +72,7 @@
post_body = json.dumps(post_body)
resp, body = self.post(url, post_body)
self.validate_response(schema.add_remove_floating_ip, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def disassociate_floating_ip_from_server(self, floating_ip, server_id):
"""Disassociate the provided floating IP from a specific server."""
@@ -87,12 +86,12 @@
post_body = json.dumps(post_body)
resp, body = self.post(url, post_body)
self.validate_response(schema.add_remove_floating_ip, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
try:
self.get_floating_ip_details(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
@@ -110,7 +109,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.floating_ip_pools, resp, body)
- return resp, body['floating_ip_pools']
+ return service_client.ResponseBodyList(resp, body['floating_ip_pools'])
def create_floating_ips_bulk(self, ip_range, pool, interface):
"""Allocate floating IPs in bulk."""
@@ -123,14 +122,15 @@
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 resp, body['floating_ips_bulk_create']
+ return service_client.ResponseBody(resp,
+ body['floating_ips_bulk_create'])
def list_floating_ips_bulk(self):
"""Returns a list of all floating IPs bulk."""
resp, body = self.get('os-floating-ips-bulk')
body = json.loads(body)
self.validate_response(schema.list_floating_ips_bulk, resp, body)
- return resp, body['floating_ip_info']
+ return service_client.ResponseBodyList(resp, body['floating_ip_info'])
def delete_floating_ips_bulk(self, ip_range):
"""Deletes the provided floating IPs bulk."""
@@ -138,4 +138,5 @@
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 resp, body['floating_ips_bulk_delete']
+ data = body['floating_ips_bulk_delete']
+ return service_client.ResponseBodyData(resp, data)
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index a5755da..0ceb6d1 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -16,10 +16,11 @@
import json
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute.v2 import images as schema
from tempest.common import service_client
from tempest.common import waiters
-from tempest import exceptions
class ImagesClientJSON(service_client.ServiceClient):
@@ -131,7 +132,7 @@
def is_resource_deleted(self, id):
try:
self.get_image(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/compute/json/instance_usage_audit_log_client.py b/tempest/services/compute/json/instance_usage_audit_log_client.py
index 80d7334..551d751 100644
--- a/tempest/services/compute/json/instance_usage_audit_log_client.py
+++ b/tempest/services/compute/json/instance_usage_audit_log_client.py
@@ -28,11 +28,13 @@
body = json.loads(body)
self.validate_response(schema.list_instance_usage_audit_log,
resp, body)
- return resp, body["instance_usage_audit_logs"]
+ return service_client.ResponseBody(resp,
+ body["instance_usage_audit_logs"])
def get_instance_usage_audit_log(self, time_before):
url = 'os-instance_usage_audit_log/%s' % time_before
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.get_instance_usage_audit_log, resp, body)
- return resp, body["instance_usage_audit_log"]
+ return service_client.ResponseBody(resp,
+ body["instance_usage_audit_log"])
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 595b23c..0c5516c 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -29,7 +29,8 @@
resp, body = self.get('servers/%s/os-interface' % server)
body = json.loads(body)
self.validate_response(schema.list_interfaces, resp, body)
- return resp, body['interfaceAttachments']
+ return service_client.ResponseBodyList(resp,
+ body['interfaceAttachments'])
def create_interface(self, server, port_id=None, network_id=None,
fixed_ip=None):
@@ -45,28 +46,28 @@
resp, body = self.post('servers/%s/os-interface' % server,
body=post_body)
body = json.loads(body)
- return resp, body['interfaceAttachment']
+ return service_client.ResponseBody(resp, body['interfaceAttachment'])
def show_interface(self, server, port_id):
resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id))
body = json.loads(body)
- return resp, body['interfaceAttachment']
+ return service_client.ResponseBody(resp, body['interfaceAttachment'])
def delete_interface(self, server, port_id):
resp, body = self.delete('servers/%s/os-interface/%s' % (server,
port_id))
self.validate_response(common_schema.delete_interface, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def wait_for_interface_status(self, server, port_id, status):
"""Waits for a interface to reach a given status."""
- resp, body = self.show_interface(server, port_id)
+ body = self.show_interface(server, port_id)
interface_status = body['port_state']
start = int(time.time())
while(interface_status != status):
time.sleep(self.build_interval)
- resp, body = self.show_interface(server, port_id)
+ body = self.show_interface(server, port_id)
interface_status = body['port_state']
timed_out = int(time.time()) - start >= self.build_timeout
@@ -78,7 +79,7 @@
self.build_timeout))
raise exceptions.TimeoutException(message)
- return resp, body
+ return body
def add_fixed_ip(self, server_id, network_id):
"""Add a fixed IP to input server instance."""
@@ -91,7 +92,7 @@
post_body)
self.validate_response(servers_schema.server_actions_common_schema,
resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def remove_fixed_ip(self, server_id, ip_address):
"""Remove input fixed IP from input server instance."""
@@ -104,4 +105,4 @@
post_body)
self.validate_response(servers_schema.server_actions_common_schema,
resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index b41abc8..a65b655 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -31,4 +31,4 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_migrations, resp, body)
- return resp, body['migrations']
+ return service_client.ResponseBodyList(resp, body['migrations'])
diff --git a/tempest/services/compute/json/networks_client.py b/tempest/services/compute/json/networks_client.py
index 361258a..ef1c058 100644
--- a/tempest/services/compute/json/networks_client.py
+++ b/tempest/services/compute/json/networks_client.py
@@ -24,10 +24,10 @@
resp, body = self.get("os-networks")
body = json.loads(body)
self.expected_success(200, resp.status)
- return resp, body['networks']
+ return service_client.ResponseBodyList(resp, body['networks'])
def get_network(self, network_id):
resp, body = self.get("os-networks/%s" % str(network_id))
body = json.loads(body)
self.expected_success(200, resp.status)
- return resp, body['network']
+ return service_client.ResponseBody(resp, body['network'])
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index 410ad60..5aefa7b 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -16,9 +16,10 @@
import json
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute.v2 import security_groups as schema
from tempest.common import service_client
-from tempest import exceptions
class SecurityGroupsClientJSON(service_client.ServiceClient):
@@ -128,12 +129,12 @@
for sg in body['security_groups']:
if sg['id'] == security_group_id:
return service_client.ResponseBodyList(resp, sg['rules'])
- raise exceptions.NotFound('No such Security Group')
+ raise lib_exc.NotFound('No such Security Group')
def is_resource_deleted(self, id):
try:
self.get_security_group(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index cbe1ca8..bd4fd0e 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -18,18 +18,23 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute import servers as common_schema
from tempest.api_schema.response.compute.v2 import servers as schema
from tempest.common import service_client
from tempest.common import waiters
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
-
class ServersClientJSON(service_client.ServiceClient):
+ def __init__(self, auth_provider, service, region,
+ enable_instance_password=True, **kwargs):
+ super(ServersClientJSON, self).__init__(
+ auth_provider, service, region, **kwargs)
+ self.enable_instance_password = enable_instance_password
+
def create_server(self, name, image_ref, flavor_ref, **kwargs):
"""
Creates an instance of a server.
@@ -90,13 +95,13 @@
# NOTE(maurosr): this deals with the case of multiple server create
# with return reservation id set True
if 'reservation_id' in body:
- return resp, body
- if CONF.compute_feature_enabled.enable_instance_password:
+ return service_client.ResponseBody(resp, body)
+ if self.enable_instance_password:
create_schema = schema.create_server_with_admin_pass
else:
create_schema = schema.create_server
self.validate_response(create_schema, resp, body)
- return resp, body['server']
+ return service_client.ResponseBody(resp, body['server'])
def update_server(self, server_id, name=None, meta=None, accessIPv4=None,
accessIPv6=None, disk_config=None):
@@ -130,20 +135,20 @@
resp, body = self.put("servers/%s" % str(server_id), post_body)
body = json.loads(body)
self.validate_response(schema.update_server, resp, body)
- return resp, body['server']
+ return service_client.ResponseBody(resp, body['server'])
def get_server(self, server_id):
"""Returns the details of an existing server."""
resp, body = self.get("servers/%s" % str(server_id))
body = json.loads(body)
self.validate_response(schema.get_server, resp, body)
- return resp, body['server']
+ return service_client.ResponseBody(resp, body['server'])
def delete_server(self, server_id):
"""Deletes the given server."""
resp, body = self.delete("servers/%s" % str(server_id))
self.validate_response(common_schema.delete_server, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def list_servers(self, params=None):
"""Lists all servers for a user."""
@@ -155,7 +160,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(common_schema.list_servers, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def list_servers_with_detail(self, params=None):
"""Lists all servers in detail for a user."""
@@ -167,7 +172,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_servers_detail, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def wait_for_server_status(self, server_id, status, extra_timeout=0,
raise_on_error=True, ready_wait=True):
@@ -182,8 +187,8 @@
start_time = int(time.time())
while True:
try:
- resp, body = self.get_server(server_id)
- except exceptions.NotFound:
+ body = self.get_server(server_id)
+ except lib_exc.NotFound:
return
server_status = body['status']
@@ -200,7 +205,7 @@
resp, body = self.get("servers/%s/ips" % str(server_id))
body = json.loads(body)
self.validate_response(schema.list_addresses, resp, body)
- return resp, body['addresses']
+ return service_client.ResponseBody(resp, body['addresses'])
def list_addresses_by_network(self, server_id, network_id):
"""Lists all addresses of a specific network type for a server."""
@@ -208,10 +213,11 @@
(str(server_id), network_id))
body = json.loads(body)
self.validate_response(schema.list_addresses_by_network, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def action(self, server_id, action_name, response_key,
- schema=common_schema.server_actions_common_schema, **kwargs):
+ schema=common_schema.server_actions_common_schema,
+ response_class=service_client.ResponseBody, **kwargs):
post_body = json.dumps({action_name: kwargs})
resp, body = self.post('servers/%s/action' % str(server_id),
post_body)
@@ -229,7 +235,7 @@
body = body[response_key]
else:
self.validate_response(schema, resp, body)
- return resp, body
+ return response_class(resp, body)
def create_backup(self, server_id, backup_type, rotation, name):
"""Backup a server instance."""
@@ -248,7 +254,7 @@
str(server_id))
body = json.loads(body)
self.validate_response(common_schema.get_password, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def delete_password(self, server_id):
"""
@@ -260,7 +266,7 @@
str(server_id))
self.validate_response(common_schema.server_actions_delete_password,
resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def reboot(self, server_id, reboot_type):
"""Reboots a server."""
@@ -272,7 +278,7 @@
if 'disk_config' in kwargs:
kwargs['OS-DCF:diskConfig'] = kwargs['disk_config']
del kwargs['disk_config']
- if CONF.compute_feature_enabled.enable_instance_password:
+ if self.enable_instance_password:
rebuild_schema = schema.rebuild_server_with_admin_pass
else:
rebuild_schema = schema.rebuild_server
@@ -301,7 +307,7 @@
resp, body = self.get("servers/%s/metadata" % str(server_id))
body = json.loads(body)
self.validate_response(common_schema.list_server_metadata, resp, body)
- return resp, body['metadata']
+ return service_client.ResponseBody(resp, body['metadata'])
def set_server_metadata(self, server_id, meta, no_metadata_field=False):
if no_metadata_field:
@@ -312,7 +318,7 @@
post_body)
body = json.loads(body)
self.validate_response(common_schema.set_server_metadata, resp, body)
- return resp, body['metadata']
+ return service_client.ResponseBody(resp, body['metadata'])
def update_server_metadata(self, server_id, meta):
post_body = json.dumps({'metadata': meta})
@@ -321,14 +327,14 @@
body = json.loads(body)
self.validate_response(common_schema.update_server_metadata,
resp, body)
- return resp, body['metadata']
+ return service_client.ResponseBody(resp, body['metadata'])
def get_server_metadata_item(self, server_id, key):
resp, body = self.get("servers/%s/metadata/%s" % (str(server_id), key))
body = json.loads(body)
self.validate_response(schema.set_get_server_metadata_item,
resp, body)
- return resp, body['meta']
+ return service_client.ResponseBody(resp, body['meta'])
def set_server_metadata_item(self, server_id, key, meta):
post_body = json.dumps({'meta': meta})
@@ -337,14 +343,14 @@
body = json.loads(body)
self.validate_response(schema.set_get_server_metadata_item,
resp, body)
- return resp, body['meta']
+ return service_client.ResponseBody(resp, body['meta'])
def delete_server_metadata_item(self, server_id, key):
resp, body = self.delete("servers/%s/metadata/%s" %
(str(server_id), key))
self.validate_response(common_schema.delete_server_metadata_item,
resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def stop(self, server_id, **kwargs):
return self.action(server_id, 'os-stop', None, **kwargs)
@@ -364,14 +370,14 @@
post_body)
body = json.loads(body)
self.validate_response(schema.attach_volume, resp, body)
- return resp, body['volumeAttachment']
+ return service_client.ResponseBody(resp, body['volumeAttachment'])
def detach_volume(self, server_id, volume_id):
"""Detaches a volume from a server instance."""
resp, body = self.delete('servers/%s/os-volume_attachments/%s' %
(server_id, volume_id))
self.validate_response(schema.detach_volume, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def get_volume_attachment(self, server_id, attach_id):
"""Return details about the given volume attachment."""
@@ -379,7 +385,7 @@
str(server_id), attach_id))
body = json.loads(body)
self.validate_response(schema.get_volume_attachment, resp, body)
- return resp, body['volumeAttachment']
+ return service_client.ResponseBody(resp, body['volumeAttachment'])
def list_volume_attachments(self, server_id):
"""Returns the list of volume attachments for a given instance."""
@@ -387,7 +393,7 @@
str(server_id)))
body = json.loads(body)
self.validate_response(schema.list_volume_attachments, resp, body)
- return resp, body['volumeAttachments']
+ return service_client.ResponseBodyList(resp, body['volumeAttachments'])
def add_security_group(self, server_id, name):
"""Adds a security group to the server."""
@@ -411,7 +417,7 @@
resp, body = self.post("servers/%s/action" % str(server_id), req_body)
self.validate_response(common_schema.server_actions_common_schema,
resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def migrate_server(self, server_id, **kwargs):
"""Migrates a server to a new host."""
@@ -460,7 +466,9 @@
def get_console_output(self, server_id, length):
kwargs = {'length': length} if length else {}
return self.action(server_id, 'os-getConsoleOutput', 'output',
- common_schema.get_console_output, **kwargs)
+ common_schema.get_console_output,
+ response_class=service_client.ResponseBodyData,
+ **kwargs)
def list_virtual_interfaces(self, server_id):
"""
@@ -470,12 +478,14 @@
'os-virtual-interfaces']))
body = json.loads(body)
self.validate_response(schema.list_virtual_interfaces, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server."""
return self.action(server_id, 'rescue', 'adminPass',
- schema.rescue_server, **kwargs)
+ schema.rescue_server,
+ response_class=service_client.ResponseBodyData,
+ **kwargs)
def unrescue_server(self, server_id):
"""Unrescue the provided server."""
@@ -484,7 +494,7 @@
def get_server_diagnostics(self, server_id):
"""Get the usage data for a server."""
resp, body = self.get("servers/%s/diagnostics" % str(server_id))
- return resp, json.loads(body)
+ return service_client.ResponseBody(resp, json.loads(body))
def list_instance_actions(self, server_id):
"""List the provided server action."""
@@ -492,7 +502,7 @@
str(server_id))
body = json.loads(body)
self.validate_response(schema.list_instance_actions, resp, body)
- return resp, body['instanceActions']
+ return service_client.ResponseBodyList(resp, body['instanceActions'])
def get_instance_action(self, server_id, request_id):
"""Returns the action details of the provided server."""
@@ -500,7 +510,7 @@
(str(server_id), str(request_id)))
body = json.loads(body)
self.validate_response(schema.get_instance_action, resp, body)
- return resp, body['instanceAction']
+ return service_client.ResponseBody(resp, body['instanceAction'])
def force_delete_server(self, server_id, **kwargs):
"""Force delete a server."""
@@ -540,24 +550,24 @@
body = json.loads(body)
self.validate_response(schema.create_get_server_group, resp, body)
- return resp, body['server_group']
+ return service_client.ResponseBody(resp, body['server_group'])
def delete_server_group(self, server_group_id):
"""Delete the given server-group."""
resp, body = self.delete("os-server-groups/%s" % str(server_group_id))
self.validate_response(schema.delete_server_group, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def list_server_groups(self):
"""List the server-groups."""
resp, body = self.get("os-server-groups")
body = json.loads(body)
self.validate_response(schema.list_server_groups, resp, body)
- return resp, body['server_groups']
+ return service_client.ResponseBodyList(resp, body['server_groups'])
def get_server_group(self, server_group_id):
"""Get the details of given server_group."""
resp, body = self.get("os-server-groups/%s" % str(server_group_id))
body = json.loads(body)
self.validate_response(schema.create_get_server_group, resp, body)
- return resp, body['server_group']
+ return service_client.ResponseBody(resp, body['server_group'])
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index 5dc1d5d..bbc1051 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -30,7 +30,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_tenant, resp, body)
- return resp, body['tenant_usages'][0]
+ return service_client.ResponseBodyList(resp, body['tenant_usages'][0])
def get_tenant_usage(self, tenant_id, params=None):
url = 'os-simple-tenant-usage/%s' % tenant_id
@@ -40,4 +40,4 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.get_tenant, resp, body)
- return resp, body['tenant_usage']
+ return service_client.ResponseBodyList(resp, body['tenant_usage'])
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index 61d0b23..a9cada8 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -17,6 +17,8 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.api_schema.response.compute.v2 import volumes as schema
from tempest.common import service_client
from tempest import exceptions
@@ -33,7 +35,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_volumes, resp, body)
- return resp, body['volumes']
+ return service_client.ResponseBodyList(resp, body['volumes'])
def list_volumes_with_detail(self, params=None):
"""List all the details of volumes."""
@@ -44,7 +46,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.list_volumes, resp, body)
- return resp, body['volumes']
+ return service_client.ResponseBodyList(resp, body['volumes'])
def get_volume(self, volume_id):
"""Returns the details of a single volume."""
@@ -52,7 +54,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.validate_response(schema.create_get_volume, resp, body)
- return resp, body['volume']
+ return service_client.ResponseBody(resp, body['volume'])
def create_volume(self, size, **kwargs):
"""
@@ -71,23 +73,23 @@
resp, body = self.post('os-volumes', post_body)
body = json.loads(body)
self.validate_response(schema.create_get_volume, resp, body)
- return resp, body['volume']
+ return service_client.ResponseBody(resp, body['volume'])
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
resp, body = self.delete("os-volumes/%s" % str(volume_id))
self.validate_response(schema.delete_volume, resp, body)
- return resp, body
+ return service_client.ResponseBody(resp, body)
def wait_for_volume_status(self, volume_id, status):
"""Waits for a Volume to reach a given status."""
- resp, body = self.get_volume(volume_id)
+ body = self.get_volume(volume_id)
volume_status = body['status']
start = int(time.time())
while volume_status != status:
time.sleep(self.build_interval)
- resp, body = self.get_volume(volume_id)
+ body = self.get_volume(volume_id)
volume_status = body['status']
if volume_status == 'error':
raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
@@ -102,7 +104,7 @@
def is_resource_deleted(self, id):
try:
self.get_volume(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/data_processing/v1_1/client.py b/tempest/services/data_processing/v1_1/data_processing_client.py
similarity index 79%
rename from tempest/services/data_processing/v1_1/client.py
rename to tempest/services/data_processing/v1_1/data_processing_client.py
index 55b6be6..04cf9a3 100644
--- a/tempest/services/data_processing/v1_1/client.py
+++ b/tempest/services/data_processing/v1_1/data_processing_client.py
@@ -15,25 +15,25 @@
import json
from tempest.common import service_client
-from tempest import config
-
-CONF = config.CONF
class DataProcessingClient(service_client.ServiceClient):
- def __init__(self, auth_provider):
- super(DataProcessingClient, self).__init__(
- auth_provider,
- CONF.data_processing.catalog_type,
- CONF.identity.region,
- endpoint_type=CONF.data_processing.endpoint_type)
-
def _request_and_check_resp(self, request_func, uri, resp_status):
"""Make a request using specified request_func and check response
status code.
- It returns pair: resp and response body.
+ It returns a ResponseBody.
+ """
+ resp, body = request_func(uri)
+ self.expected_success(resp_status, resp.status)
+ return service_client.ResponseBody(resp, body)
+
+ def _request_and_check_resp_data(self, request_func, uri, resp_status):
+ """Make a request using specified request_func and check response
+ status code.
+
+ It returns pair: resp and response data.
"""
resp, body = request_func(uri)
self.expected_success(resp_status, resp.status)
@@ -44,20 +44,35 @@
"""Make a request using specified request_func, check response status
code and parse response body.
- It returns pair: resp and parsed resource(s) body.
+ It returns a ResponseBody.
"""
headers = {'Content-Type': 'application/json'}
resp, body = request_func(uri, headers=headers, *args, **kwargs)
self.expected_success(resp_status, resp.status)
body = json.loads(body)
- return resp, body[resource_name]
+ return service_client.ResponseBody(resp, body[resource_name])
+
+ def _request_check_and_parse_resp_list(self, request_func, uri,
+ resp_status, resource_name,
+ *args, **kwargs):
+ """Make a request using specified request_func, check response status
+ code and parse response body.
+
+ It returns a ResponseBodyList.
+ """
+ headers = {'Content-Type': 'application/json'}
+ resp, body = request_func(uri, headers=headers, *args, **kwargs)
+ self.expected_success(resp_status, resp.status)
+ body = json.loads(body)
+ return service_client.ResponseBodyList(resp, body[resource_name])
def list_node_group_templates(self):
"""List all node group templates for a user."""
uri = 'node-group-templates'
- return self._request_check_and_parse_resp(self.get, uri,
- 200, 'node_group_templates')
+ return self._request_check_and_parse_resp_list(self.get, uri,
+ 200,
+ 'node_group_templates')
def get_node_group_template(self, tmpl_id):
"""Returns the details of a single node group template."""
@@ -98,8 +113,8 @@
"""List all enabled plugins."""
uri = 'plugins'
- return self._request_check_and_parse_resp(self.get,
- uri, 200, 'plugins')
+ return self._request_check_and_parse_resp_list(self.get,
+ uri, 200, 'plugins')
def get_plugin(self, plugin_name, plugin_version=None):
"""Returns the details of a single plugin."""
@@ -113,8 +128,9 @@
"""List all cluster templates for a user."""
uri = 'cluster-templates'
- return self._request_check_and_parse_resp(self.get, uri,
- 200, 'cluster_templates')
+ return self._request_check_and_parse_resp_list(self.get, uri,
+ 200,
+ 'cluster_templates')
def get_cluster_template(self, tmpl_id):
"""Returns the details of a single cluster template."""
@@ -154,8 +170,9 @@
"""List all data sources for a user."""
uri = 'data-sources'
- return self._request_check_and_parse_resp(self.get,
- uri, 200, 'data_sources')
+ return self._request_check_and_parse_resp_list(self.get,
+ uri, 200,
+ 'data_sources')
def get_data_source(self, source_id):
"""Returns the details of a single data source."""
@@ -191,8 +208,8 @@
"""List all job binary internals for a user."""
uri = 'job-binary-internals'
- return self._request_check_and_parse_resp(self.get,
- uri, 200, 'binaries')
+ return self._request_check_and_parse_resp_list(self.get,
+ uri, 200, 'binaries')
def get_job_binary_internal(self, job_binary_id):
"""Returns the details of a single job binary internal."""
@@ -218,14 +235,14 @@
"""Returns data of a single job binary internal."""
uri = 'job-binary-internals/%s/data' % job_binary_id
- return self._request_and_check_resp(self.get, uri, 200)
+ return self._request_and_check_resp_data(self.get, uri, 200)
def list_job_binaries(self):
"""List all job binaries for a user."""
uri = 'job-binaries'
- return self._request_check_and_parse_resp(self.get,
- uri, 200, 'binaries')
+ return self._request_check_and_parse_resp_list(self.get,
+ uri, 200, 'binaries')
def get_job_binary(self, job_binary_id):
"""Returns the details of a single job binary."""
@@ -261,13 +278,14 @@
"""Returns data of a single job binary."""
uri = 'job-binaries/%s/data' % job_binary_id
- return self._request_and_check_resp(self.get, uri, 200)
+ return self._request_and_check_resp_data(self.get, uri, 200)
def list_jobs(self):
"""List all jobs for a user."""
uri = 'jobs'
- return self._request_check_and_parse_resp(self.get, uri, 200, 'jobs')
+ return self._request_check_and_parse_resp_list(self.get,
+ uri, 200, 'jobs')
def get_job(self, job_id):
"""Returns the details of a single job."""
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
index dfb2eb3..c956e27 100644
--- a/tempest/services/database/json/flavors_client.py
+++ b/tempest/services/database/json/flavors_client.py
@@ -27,9 +27,9 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return resp, self._parse_resp(body)
+ return service_client.ResponseBodyList(resp, self._parse_resp(body))
def get_db_flavor_details(self, db_flavor_id):
resp, body = self.get("flavors/%s" % str(db_flavor_id))
self.expected_success(200, resp.status)
- return resp, self._parse_resp(body)
+ return service_client.ResponseBody(resp, self._parse_resp(body))
diff --git a/tempest/services/database/json/limits_client.py b/tempest/services/database/json/limits_client.py
index 4daf028..ae758bc 100644
--- a/tempest/services/database/json/limits_client.py
+++ b/tempest/services/database/json/limits_client.py
@@ -15,13 +15,10 @@
import urllib
-from tempest import config
-from tempest_lib.common import rest_client
-
-CONF = config.CONF
+from tempest.common import service_client
-class DatabaseLimitsClientJSON(rest_client.RestClient):
+class DatabaseLimitsClientJSON(service_client.ServiceClient):
def list_db_limits(self, params=None):
"""List all limits."""
@@ -30,4 +27,4 @@
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return resp, self._parse_resp(body)
+ return service_client.ResponseBodyList(resp, self._parse_resp(body))
diff --git a/tempest/services/database/json/versions_client.py b/tempest/services/database/json/versions_client.py
index c3388bb..aa2fef7 100644
--- a/tempest/services/database/json/versions_client.py
+++ b/tempest/services/database/json/versions_client.py
@@ -43,4 +43,4 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return resp, self._parse_resp(body)
+ return service_client.ResponseBodyList(resp, self._parse_resp(body))
diff --git a/tempest/services/identity/json/__init__.py b/tempest/services/identity/v2/__init__.py
similarity index 100%
copy from tempest/services/identity/json/__init__.py
copy to tempest/services/identity/v2/__init__.py
diff --git a/tempest/services/identity/json/__init__.py b/tempest/services/identity/v2/json/__init__.py
similarity index 100%
rename from tempest/services/identity/json/__init__.py
rename to tempest/services/identity/v2/json/__init__.py
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
similarity index 96%
rename from tempest/services/identity/json/identity_client.py
rename to tempest/services/identity/v2/json/identity_client.py
index d4f57e0..6c4a6b4 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -11,23 +11,13 @@
# under the License.
import json
+from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
class IdentityClientJSON(service_client.ServiceClient):
- def __init__(self, auth_provider):
- super(IdentityClientJSON, self).__init__(
- auth_provider,
- CONF.identity.catalog_type,
- CONF.identity.region,
- endpoint_type='adminURL')
-
def has_admin_extensions(self):
"""
Returns True if the KSADM Admin Extensions are supported
@@ -134,7 +124,7 @@
for tenant in tenants:
if tenant['name'] == tenant_name:
return tenant
- raise exceptions.NotFound('No such tenant')
+ raise lib_exc.NotFound('No such tenant')
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant."""
@@ -227,7 +217,7 @@
for user in users:
if user['name'] == username:
return user
- raise exceptions.NotFound('No such user')
+ raise lib_exc.NotFound('No such user')
def create_service(self, name, type, **kwargs):
"""Create a service."""
diff --git a/tempest/services/identity/json/token_client.py b/tempest/services/identity/v2/json/token_client.py
similarity index 84%
rename from tempest/services/identity/json/token_client.py
rename to tempest/services/identity/v2/json/token_client.py
index 93936bc..e61ac84 100644
--- a/tempest/services/identity/json/token_client.py
+++ b/tempest/services/identity/v2/json/token_client.py
@@ -13,19 +13,21 @@
# under the License.
import json
+from tempest_lib.common import rest_client
+from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
+class TokenClientJSON(rest_client.RestClient):
-class TokenClientJSON(service_client.ServiceClient):
-
- def __init__(self):
- super(TokenClientJSON, self).__init__(None, None, None)
- auth_url = CONF.identity.uri
+ def __init__(self, auth_url, disable_ssl_certificate_validation=None,
+ ca_certs=None, trace_requests=None):
+ dscv = disable_ssl_certificate_validation
+ super(TokenClientJSON, self).__init__(
+ None, None, None, disable_ssl_certificate_validation=dscv,
+ ca_certs=ca_certs, trace_requests=trace_requests)
# Normalize URI to ensure /tokens is in it.
if 'tokens' not in auth_url:
@@ -87,7 +89,7 @@
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)
- raise exceptions.Unauthorized(resp_body['error']['message'])
+ raise lib_exc.Unauthorized(resp_body['error']['message'])
elif resp.status not in [200, 201]:
raise exceptions.IdentityError(
'Unexpected status code {0}'.format(resp.status))
diff --git a/tempest/services/identity/v3/json/base.py b/tempest/services/identity/v3/json/base.py
deleted file mode 100644
index cba480a..0000000
--- a/tempest/services/identity/v3/json/base.py
+++ /dev/null
@@ -1,32 +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.common import service_client
-from tempest import config
-
-CONF = config.CONF
-
-
-class IdentityV3Client(service_client.ServiceClient):
- """
- Base identity v3 client class
- """
-
- def __init__(self, auth_provider):
- super(IdentityV3Client, self).__init__(
- auth_provider,
- CONF.identity.catalog_type,
- CONF.identity.region,
- endpoint_type='adminURL')
- self.api_version = "v3"
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/services/identity/v3/json/credentials_client.py
index 1289e48..0a614cd 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/services/identity/v3/json/credentials_client.py
@@ -16,10 +16,10 @@
import json
from tempest.common import service_client
-from tempest.services.identity.v3.json import base
-class CredentialsClientJSON(base.IdentityV3Client):
+class CredentialsClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def create_credential(self, access_key, secret_key, user_id, project_id):
"""Creates a credential."""
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/services/identity/v3/json/endpoints_client.py
index d71836e..5b7e812 100644
--- a/tempest/services/identity/v3/json/endpoints_client.py
+++ b/tempest/services/identity/v3/json/endpoints_client.py
@@ -16,10 +16,10 @@
import json
from tempest.common import service_client
-from tempest.services.identity.v3.json import base
-class EndPointClientJSON(base.IdentityV3Client):
+class EndPointClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def list_endpoints(self):
"""GET endpoints."""
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index f3d9d2d..be5aa80 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -17,13 +17,10 @@
import urllib
from tempest.common import service_client
-from tempest import config
-from tempest.services.identity.v3.json import base
-
-CONF = config.CONF
-class IdentityV3ClientJSON(base.IdentityV3Client):
+class IdentityV3ClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def create_user(self, user_name, password=None, project_id=None,
email=None, domain_id='default', **kwargs):
diff --git a/tempest/services/identity/v3/json/policy_client.py b/tempest/services/identity/v3/json/policy_client.py
index 25931c8..8c9c9ce 100644
--- a/tempest/services/identity/v3/json/policy_client.py
+++ b/tempest/services/identity/v3/json/policy_client.py
@@ -16,10 +16,10 @@
import json
from tempest.common import service_client
-from tempest.services.identity.v3.json import base
-class PolicyClientJSON(base.IdentityV3Client):
+class PolicyClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def create_policy(self, blob, type):
"""Creates a Policy."""
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/region_client.py
index 482cbc6..faaf43c 100644
--- a/tempest/services/identity/v3/json/region_client.py
+++ b/tempest/services/identity/v3/json/region_client.py
@@ -17,10 +17,10 @@
import urllib
from tempest.common import service_client
-from tempest.services.identity.v3.json import base
-class RegionClientJSON(base.IdentityV3Client):
+class RegionClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def create_region(self, description, **kwargs):
"""Create region."""
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index 2e2df13..e039dc6 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -16,10 +16,10 @@
import json
from tempest.common import service_client
-from tempest.services.identity.v3.json import base
-class ServiceClientJSON(base.IdentityV3Client):
+class ServiceClientJSON(service_client.ServiceClient):
+ api_version = "v3"
def update_service(self, service_id, **kwargs):
"""Updates a service."""
diff --git a/tempest/services/identity/v3/json/token_client.py b/tempest/services/identity/v3/json/token_client.py
index 14c4a0a..b0824a7 100644
--- a/tempest/services/identity/v3/json/token_client.py
+++ b/tempest/services/identity/v3/json/token_client.py
@@ -13,19 +13,21 @@
# under the License.
import json
+from tempest_lib.common import rest_client
+from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
+class V3TokenClientJSON(rest_client.RestClient):
-class V3TokenClientJSON(service_client.ServiceClient):
-
- def __init__(self):
- super(V3TokenClientJSON, self).__init__(None, None, None)
- auth_url = CONF.identity.uri_v3
+ def __init__(self, auth_url, disable_ssl_certificate_validation=None,
+ ca_certs=None, trace_requests=None):
+ dscv = disable_ssl_certificate_validation
+ super(V3TokenClientJSON, self).__init__(
+ None, None, None, disable_ssl_certificate_validation=dscv,
+ ca_certs=ca_certs, trace_requests=trace_requests)
if not auth_url:
raise exceptions.InvalidConfiguration('you must specify a v3 uri '
'if using the v3 identity '
@@ -35,23 +37,22 @@
self.auth_url = auth_url
- def auth(self, user=None, password=None, tenant=None, user_type='id',
- domain=None, token=None):
+ def auth(self, user=None, password=None, project=None, user_type='id',
+ user_domain=None, project_domain=None, token=None):
"""
:param user: user id or name, as specified in user_type
- :param domain: the user and tenant domain
+ :param user_domain: the user domain
+ :param project_domain: the project domain
:param token: a token to re-scope.
Accepts different combinations of credentials. Restrictions:
- - tenant and domain are only name (no id)
- - user domain and tenant domain are assumed identical
- - domain scope is not supported here
+ - project and domain are only name (no id)
Sample sample valid combinations:
- token
- - token, tenant, domain
+ - token, project, project_domain
- user_id, password
- - username, password, domain
- - username, password, tenant, domain
+ - username, password, user_domain
+ - username, password, project, user_domain, project_domain
Validation is left to the server side.
"""
creds = {
@@ -78,13 +79,13 @@
id_obj['password']['user']['id'] = user
else:
id_obj['password']['user']['name'] = user
- if domain is not None:
- _domain = dict(name=domain)
+ if user_domain is not None:
+ _domain = dict(name=user_domain)
id_obj['password']['user']['domain'] = _domain
- if tenant is not None:
- _domain = dict(name=domain)
- project = dict(name=tenant, domain=_domain)
- scope = dict(project=project)
+ if project is not None:
+ _domain = dict(name=project_domain)
+ _project = dict(name=project, domain=_domain)
+ scope = dict(project=_project)
creds['auth']['scope'] = scope
body = json.dumps(creds)
@@ -112,21 +113,22 @@
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)
- raise exceptions.Unauthorized(resp_body['error']['message'])
+ raise lib_exc.Unauthorized(resp_body['error']['message'])
elif resp.status not in [200, 201, 204]:
raise exceptions.IdentityError(
'Unexpected status code {0}'.format(resp.status))
return resp, json.loads(resp_body)
- def get_token(self, user, password, tenant, domain='Default',
- auth_data=False):
+ def get_token(self, user, password, project=None, project_domain='Default',
+ user_domain='Default', auth_data=False):
"""
:param user: username
Returns (token id, token data) for supplied credentials
"""
- body = self.auth(user, password, tenant, user_type='name',
- domain=domain)
+ body = self.auth(user, password, project, user_type='name',
+ user_domain=user_domain,
+ project_domain=project_domain)
token = body.response.get('x-subject-token')
if auth_data:
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index a7b8f63..50f75b3 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -20,29 +20,37 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.common import glance_http
from tempest.common import service_client
from tempest.common.utils import misc as misc_utils
-from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
-CONF = config.CONF
-
LOG = logging.getLogger(__name__)
class ImageClientJSON(service_client.ServiceClient):
- def __init__(self, auth_provider):
+ def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
+ build_interval=None, build_timeout=None,
+ disable_ssl_certificate_validation=None,
+ ca_certs=None, **kwargs):
super(ImageClientJSON, self).__init__(
auth_provider,
- CONF.image.catalog_type,
- CONF.image.region or CONF.identity.region,
- endpoint_type=CONF.image.endpoint_type,
- build_interval=CONF.image.build_interval,
- build_timeout=CONF.image.build_timeout)
+ catalog_type,
+ region,
+ endpoint_type=endpoint_type,
+ build_interval=build_interval,
+ build_timeout=build_timeout,
+ disable_ssl_certificate_validation=(
+ disable_ssl_certificate_validation),
+ ca_certs=ca_certs,
+ **kwargs)
self._http = None
+ self.dscv = disable_ssl_certificate_validation
+ self.ca_certs = ca_certs
def _image_meta_from_headers(self, headers):
meta = {'properties': {}}
@@ -110,11 +118,10 @@
return None
def _get_http(self):
- dscv = CONF.identity.disable_ssl_certificate_validation
- ca_certs = CONF.identity.ca_certificates_file
return glance_http.HTTPClient(auth_provider=self.auth_provider,
filters=self.filters,
- insecure=dscv, ca_certs=ca_certs)
+ insecure=self.dscv,
+ ca_certs=self.ca_certs)
def _create_with_data(self, headers, data):
resp, body_iter = self.http.raw_request('POST', '/v1/images',
@@ -136,8 +143,7 @@
@property
def http(self):
if self._http is None:
- if CONF.service_available.glance:
- self._http = self._get_http()
+ self._http = self._get_http()
return self._http
def create_image(self, name, container_format, disk_format, **kwargs):
@@ -237,13 +243,12 @@
url = 'v1/images/%s' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
- # We can't return a ResponseBody because the body is a string
- return resp, body
+ return service_client.ResponseBodyData(resp, body)
def is_resource_deleted(self, id):
try:
self.get_image_meta(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 4b1d52d..e55a824 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -17,33 +17,38 @@
import urllib
import jsonschema
+from tempest_lib import exceptions as lib_exc
from tempest.common import glance_http
from tempest.common import service_client
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
class ImageClientV2JSON(service_client.ServiceClient):
- def __init__(self, auth_provider):
+ def __init__(self, auth_provider, catalog_type, region, endpoint_type=None,
+ build_interval=None, build_timeout=None,
+ disable_ssl_certificate_validation=None, ca_certs=None,
+ **kwargs):
super(ImageClientV2JSON, self).__init__(
auth_provider,
- CONF.image.catalog_type,
- CONF.image.region or CONF.identity.region,
- endpoint_type=CONF.image.endpoint_type,
- build_interval=CONF.image.build_interval,
- build_timeout=CONF.image.build_timeout)
+ catalog_type,
+ region,
+ endpoint_type=endpoint_type,
+ build_interval=build_interval,
+ build_timeout=build_timeout,
+ disable_ssl_certificate_validation=(
+ disable_ssl_certificate_validation),
+ ca_certs=ca_certs,
+ **kwargs)
self._http = None
+ self.dscv = disable_ssl_certificate_validation
+ self.ca_certs = ca_certs
def _get_http(self):
- dscv = CONF.identity.disable_ssl_certificate_validation
- ca_certs = CONF.identity.ca_certificates_file
return glance_http.HTTPClient(auth_provider=self.auth_provider,
filters=self.filters,
- insecure=dscv, ca_certs=ca_certs)
+ insecure=self.dscv,
+ ca_certs=self.ca_certs)
def _validate_schema(self, body, type='image'):
if type in ['image', 'images']:
@@ -56,8 +61,7 @@
@property
def http(self):
if self._http is None:
- if CONF.service_available.glance:
- self._http = self._get_http()
+ self._http = self._get_http()
return self._http
def update_image(self, image_id, patch):
@@ -120,7 +124,7 @@
def is_resource_deleted(self, id):
try:
self.get_image(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
@@ -141,8 +145,7 @@
url = 'v2/images/%s/file' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
- # We can't return a ResponseBody because the body is a string
- return resp, body
+ return service_client.ResponseBodyData(resp, body)
def add_image_tag(self, image_id, tag):
url = 'v2/images/%s/tags/%s' % (image_id, tag)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index e92708c..87f1332 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -14,6 +14,8 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.common import service_client
from tempest.common.utils import misc
from tempest import exceptions
@@ -211,7 +213,7 @@
getattr(self, method)(id)
except AttributeError:
raise Exception("Unknown resource type %s " % resource_type)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
@@ -260,9 +262,8 @@
# expecting response in form
# {'resources': [ res1, res2] } => when pagination disabled
# {'resources': [..], 'resources_links': {}} => if pagination enabled
- pagination_suffix = "_links"
for k in res.keys():
- if k[-len(pagination_suffix):] == pagination_suffix:
+ if k.endswith("_links"):
continue
return res[k]
@@ -318,6 +319,8 @@
cur_gw_info.pop('enable_snat', None)
update_body['external_gateway_info'] = kwargs.get(
'external_gateway_info', body['router']['external_gateway_info'])
+ if 'distributed' in kwargs:
+ update_body['distributed'] = kwargs['distributed']
update_body = dict(router=update_body)
update_body = json.dumps(update_body)
resp, body = self.put(uri, update_body)
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index c813977..1a4c5d9 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -18,6 +18,8 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.common import service_client
from tempest import exceptions
@@ -159,7 +161,7 @@
try:
body = self.get_resource(
stack_identifier, resource_name)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
# ignore this, as the resource may not have
# been created yet
pass
@@ -194,7 +196,7 @@
while True:
try:
body = self.get_stack(stack_identifier)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
if status == 'DELETE_COMPLETE':
return
stack_name = body['stack_name']
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index dd899e4..a249625 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -127,7 +127,7 @@
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return resp, body
+ return service_client.ResponseBodyData(resp, body)
def alarm_set_state(self, alarm_id, state):
uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
@@ -135,4 +135,4 @@
resp, body = self.put(uri, body)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return resp, body
+ return service_client.ResponseBodyData(resp, body)
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py
index 19d320f..616f8e4 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/json/admin/volume_quotas_client.py
@@ -1,7 +1,5 @@
# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
#
-# Author: Sylvain Baubeau <sylvain.baubeau@enovance.com>
-#
# 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
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index 6049eb6..c905155 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -19,7 +19,6 @@
from tempest_lib import exceptions as lib_exc
from tempest.common import service_client
-from tempest import exceptions
class BaseVolumeTypesClientJSON(service_client.ServiceClient):
@@ -42,7 +41,7 @@
else:
msg = (" resource value is either not defined or incorrect.")
raise lib_exc.UnprocessableEntity(msg)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/volume/json/qos_client.py b/tempest/services/volume/json/qos_client.py
index 6aa56f7..14ff506 100644
--- a/tempest/services/volume/json/qos_client.py
+++ b/tempest/services/volume/json/qos_client.py
@@ -27,7 +27,7 @@
def is_resource_deleted(self, qos_id):
try:
self.get_qos(qos_id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 100b34c..8430b63 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -14,6 +14,8 @@
import time
import urllib
+from tempest_lib import exceptions as lib_exc
+
from tempest.common import service_client
from tempest import exceptions
from tempest.openstack.common import log as logging
@@ -127,7 +129,7 @@
def is_resource_deleted(self, id):
try:
self.get_snapshot(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index d834905..059664c 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -17,11 +17,10 @@
import time
import urllib
-from tempest.common import service_client
-from tempest import config
-from tempest import exceptions
+from tempest_lib import exceptions as lib_exc
-CONF = config.CONF
+from tempest.common import service_client
+from tempest import exceptions
class BaseVolumesClientJSON(service_client.ServiceClient):
@@ -31,6 +30,12 @@
create_resp = 200
+ def __init__(self, auth_provider, service, region,
+ default_volume_size=1, **kwargs):
+ super(BaseVolumesClientJSON, self).__init__(
+ auth_provider, service, region, **kwargs)
+ self.default_volume_size = default_volume_size
+
def get_attachment_from_volume(self, volume):
"""Return the element 'attachment' from input volumes."""
return volume['attachments'][0]
@@ -77,10 +82,8 @@
snapshot_id: When specified the volume is created from this snapshot
imageRef: When specified the volume is created from this image
"""
- # for bug #1293885:
- # If no size specified, read volume size from CONF
if size is None:
- size = CONF.volume.volume_size
+ size = self.default_volume_size
post_body = {'size': size}
post_body.update(kwargs)
post_body = json.dumps({'volume': post_body})
@@ -181,7 +184,7 @@
def is_resource_deleted(self, id):
try:
self.get_volume(id)
- except exceptions.NotFound:
+ except lib_exc.NotFound:
return True
return False
@@ -333,6 +336,14 @@
self.expected_success(200, resp.status)
return service_client.ResponseBody(resp, body)
+ def retype_volume(self, volume_id, volume_type, **kwargs):
+ """Updates volume with new volume type."""
+ post_body = {'new_type': volume_type}
+ post_body.update(kwargs)
+ post_body = json.dumps({'os-retype': post_body})
+ resp, body = self.post('volumes/%s/action' % volume_id, post_body)
+ self.expected_success(202, resp.status)
+
class VolumesClientJSON(BaseVolumesClientJSON):
"""
diff --git a/tempest/stress/actions/server_create_destroy.py b/tempest/stress/actions/server_create_destroy.py
index 34e299d..d0e4eea 100644
--- a/tempest/stress/actions/server_create_destroy.py
+++ b/tempest/stress/actions/server_create_destroy.py
@@ -28,7 +28,7 @@
def run(self):
name = data_utils.rand_name("instance")
self.logger.info("creating %s" % name)
- _, server = self.manager.servers_client.create_server(
+ server = self.manager.servers_client.create_server(
name, self.image, self.flavor)
server_id = server['id']
self.manager.servers_client.wait_for_server_status(server_id,
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index c473df6..b2c612e 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -74,9 +74,9 @@
self.logger.info("creating %s" % name)
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
- _, server = servers_client.create_server(name, self.image,
- self.flavor,
- **vm_args)
+ server = servers_client.create_server(name, self.image,
+ self.flavor,
+ **vm_args)
self.server_id = server['id']
if self.wait_after_vm_create:
self.manager.servers_client.wait_for_server_status(self.server_id,
@@ -104,7 +104,7 @@
def _create_floating_ip(self):
floating_cli = self.manager.floating_ips_client
- _, self.floating = floating_cli.create_floating_ip(self.floating_pool)
+ self.floating = floating_cli.create_floating_ip(self.floating_pool)
def _destroy_floating_ip(self):
cli = self.manager.floating_ips_client
@@ -144,7 +144,7 @@
cli = self.manager.floating_ips_client
def func():
- _, floating = cli.get_floating_ip_details(self.floating['id'])
+ floating = cli.get_floating_ip_details(self.floating['id'])
return floating['instance_id'] is None
if not tempest.test.call_until_true(func, self.check_timeout,
diff --git a/tempest/stress/actions/volume_attach_delete.py b/tempest/stress/actions/volume_attach_delete.py
index 9c4070f..2e1d623 100644
--- a/tempest/stress/actions/volume_attach_delete.py
+++ b/tempest/stress/actions/volume_attach_delete.py
@@ -28,7 +28,7 @@
# Step 1: create volume
name = data_utils.rand_name("volume")
self.logger.info("creating volume: %s" % name)
- _, volume = self.manager.volumes_client.create_volume(
+ volume = self.manager.volumes_client.create_volume(
size=1,
display_name=name)
self.manager.volumes_client.wait_for_volume_status(volume['id'],
@@ -38,7 +38,7 @@
# Step 2: create vm instance
vm_name = data_utils.rand_name("instance")
self.logger.info("creating vm: %s" % vm_name)
- _, server = self.manager.servers_client.create_server(
+ server = self.manager.servers_client.create_server(
vm_name, self.image, self.flavor)
server_id = server['id']
self.manager.servers_client.wait_for_server_status(server_id, 'ACTIVE')
diff --git a/tempest/stress/actions/volume_attach_verify.py b/tempest/stress/actions/volume_attach_verify.py
index 3c052ac..c013af3 100644
--- a/tempest/stress/actions/volume_attach_verify.py
+++ b/tempest/stress/actions/volume_attach_verify.py
@@ -36,9 +36,9 @@
vm_args = self.vm_extra_args.copy()
vm_args['security_groups'] = [self.sec_grp]
vm_args['key_name'] = self.key['name']
- _, server = servers_client.create_server(name, self.image,
- self.flavor,
- **vm_args)
+ server = servers_client.create_server(name, self.image,
+ self.flavor,
+ **vm_args)
self.server_id = server['id']
self.manager.servers_client.wait_for_server_status(self.server_id,
'ACTIVE')
@@ -65,7 +65,7 @@
def _create_floating_ip(self):
floating_cli = self.manager.floating_ips_client
- _, self.floating = floating_cli.create_floating_ip(self.floating_pool)
+ self.floating = floating_cli.create_floating_ip(self.floating_pool)
def _destroy_floating_ip(self):
cli = self.manager.floating_ips_client
@@ -77,7 +77,7 @@
name = data_utils.rand_name("volume")
self.logger.info("creating volume: %s" % name)
volumes_client = self.manager.volumes_client
- _, self.volume = volumes_client.create_volume(
+ self.volume = volumes_client.create_volume(
size=1,
display_name=name)
volumes_client.wait_for_volume_status(self.volume['id'],
@@ -95,7 +95,7 @@
cli = self.manager.floating_ips_client
def func():
- _, floating = cli.get_floating_ip_details(self.floating['id'])
+ floating = cli.get_floating_ip_details(self.floating['id'])
return floating['instance_id'] is None
if not tempest.test.call_until_true(func, CONF.compute.build_timeout,
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index b52eca9..161d93f 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -23,7 +23,7 @@
def cleanup():
admin_manager = clients.AdminManager()
- _, body = admin_manager.servers_client.list_servers({"all_tenants": True})
+ body = admin_manager.servers_client.list_servers({"all_tenants": True})
LOG.info("Cleanup::remove %s servers" % len(body['servers']))
for s in body['servers']:
try:
@@ -55,7 +55,7 @@
except Exception:
pass
- _, floating_ips = admin_manager.floating_ips_client.list_floating_ips()
+ floating_ips = admin_manager.floating_ips_client.list_floating_ips()
LOG.info("Cleanup::remove %s floating ips" % len(floating_ips))
for f in floating_ips:
try:
@@ -95,7 +95,7 @@
except Exception:
pass
- _, vols = admin_manager.volumes_client.list_volumes({"all_tenants": True})
+ vols = admin_manager.volumes_client.list_volumes({"all_tenants": True})
LOG.info("Cleanup::remove %s volumes" % len(vols))
for v in vols:
try:
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 49fac3d..1c27815 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -19,8 +19,8 @@
from six import moves
-from tempest import auth
from tempest import clients
+from tempest.common import cred_provider
from tempest.common import ssh
from tempest.common.utils import data_utils
from tempest import config
@@ -148,9 +148,9 @@
password,
tenant['id'],
"email")
- creds = auth.get_credentials(username=username,
- password=password,
- tenant_name=tenant_name)
+ creds = cred_provider.get_credentials(username=username,
+ password=password,
+ tenant_name=tenant_name)
manager = clients.Manager(credentials=creds)
test_obj = importutils.import_class(test['action'])
diff --git a/tempest/test.py b/tempest/test.py
index 28e1e2c..f04aff7 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -24,6 +24,7 @@
import uuid
import fixtures
+import six
import testscenarios
import testtools
@@ -62,6 +63,23 @@
return decorator
+def idempotent_id(id):
+ """Stub for metadata decorator"""
+ if not isinstance(id, six.string_types):
+ raise TypeError('Test idempotent_id must be string not %s'
+ '' % type(id).__name__)
+ uuid.UUID(id)
+
+ def decorator(f):
+ f = testtools.testcase.attr('id-%s' % id)(f)
+ if f.__doc__:
+ f.__doc__ = 'Test idempotent id: %s\n%s' % (id, f.__doc__)
+ else:
+ f.__doc__ = 'Test idempotent id: %s' % id
+ return f
+ return decorator
+
+
def get_service_list():
service_list = {
'compute': CONF.service_available.nova,
@@ -359,7 +377,7 @@
level=None))
@classmethod
- def get_client_manager(cls, interface=None):
+ def get_client_manager(cls):
"""
Returns an OpenStack client manager
"""
@@ -373,12 +391,7 @@
)
creds = cls.isolated_creds.get_primary_creds()
- params = dict(credentials=creds, service=cls._service)
- if getattr(cls, '_interface', None):
- interface = cls._interface
- if interface:
- params['interface'] = interface
- os = clients.Manager(**params)
+ os = clients.Manager(credentials=creds, service=cls._service)
return os
@classmethod
@@ -394,13 +407,12 @@
"""
Returns an instance of the Identity Admin API client
"""
- os = clients.AdminManager(interface=cls._interface,
- service=cls._service)
+ os = clients.AdminManager(service=cls._service)
admin_client = os.identity_client
return admin_client
@classmethod
- def set_network_resources(self, network=False, router=False, subnet=False,
+ def set_network_resources(cls, network=False, router=False, subnet=False,
dhcp=False):
"""Specify which network resources should be created
@@ -413,8 +425,8 @@
# in order to ensure that even if it's called multiple times in
# a chain of overloaded methods, the attribute is set only
# in the leaf class
- if not self.network_resources:
- self.network_resources = {
+ if not cls.network_resources:
+ cls.network_resources = {
'network': network,
'router': router,
'subnet': subnet,
@@ -436,8 +448,7 @@
super(NegativeAutoTest, cls).setUpClass()
os = cls.get_client_manager()
cls.client = os.negative_client
- os_admin = clients.AdminManager(interface=cls._interface,
- service=cls._service)
+ os_admin = clients.AdminManager(service=cls._service)
cls.admin_client = os_admin.negative_client
@staticmethod
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 1abe29a..17e2550 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -282,8 +282,8 @@
def test_verify_extensions_nova(self):
def fake_list_extensions():
- return (None, [{'alias': 'fake1'}, {'alias': 'fake2'},
- {'alias': 'not_fake'}])
+ return ([{'alias': 'fake1'}, {'alias': 'fake2'},
+ {'alias': 'not_fake'}])
fake_os = mock.MagicMock()
fake_os.extensions_client.list_extensions = fake_list_extensions
self.useFixture(mockpatch.PatchObject(
@@ -303,9 +303,9 @@
def test_verify_extensions_nova_all(self):
def fake_list_extensions():
- return (None, {'extensions': [{'alias': 'fake1'},
- {'alias': 'fake2'},
- {'alias': 'not_fake'}]})
+ return ({'extensions': [{'alias': 'fake1'},
+ {'alias': 'fake2'},
+ {'alias': 'not_fake'}]})
fake_os = mock.MagicMock()
fake_os.extensions_client.list_extensions = fake_list_extensions
self.useFixture(mockpatch.PatchObject(
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py
index f45f2cf..1e6b651 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_accounts.py
@@ -24,7 +24,7 @@
from tempest.common import accounts
from tempest import config
from tempest import exceptions
-from tempest.services.identity.json import token_client
+from tempest.services.identity.v2.json import token_client
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests import fake_identity
@@ -73,7 +73,8 @@
test_account_class = accounts.Accounts('test_name')
hash_list = self._get_hash_list(self.test_accounts)
test_cred_dict = self.test_accounts[3]
- test_creds = auth.get_credentials(**test_cred_dict)
+ test_creds = auth.get_credentials(fake_identity.FAKE_AUTH_URL,
+ **test_cred_dict)
results = test_account_class.get_hash(test_creds)
self.assertEqual(hash_list[3], results)
@@ -128,8 +129,9 @@
# Emulate all lcoks in list are in use
self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
test_account_class = accounts.Accounts('test_name')
- self.assertRaises(exceptions.InvalidConfiguration,
- test_account_class._get_free_hash, hash_list)
+ with mock.patch('__builtin__.open', mock.mock_open(), create=True):
+ self.assertRaises(exceptions.InvalidConfiguration,
+ test_account_class._get_free_hash, hash_list)
@mock.patch('tempest.openstack.common.lockutils.lock')
def test_get_free_hash_some_in_use_accounts(self, lock_mock):
@@ -151,7 +153,7 @@
test_account_class._get_free_hash(hash_list)
lock_path = os.path.join(accounts.CONF.lock_path, 'test_accounts',
hash_list[3])
- open_mock.assert_called_once_with(lock_path, 'w')
+ open_mock.assert_has_calls([mock.call(lock_path, 'w')])
@mock.patch('tempest.openstack.common.lockutils.lock')
def test_remove_hash_last_account(self, lock_mock):
diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_cred_provider.py
new file mode 100644
index 0000000..3f7c0f8
--- /dev/null
+++ b/tempest/tests/common/test_cred_provider.py
@@ -0,0 +1,97 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# 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.config import cfg
+
+from tempest import auth
+from tempest.common import cred_provider
+from tempest.common import tempest_fixtures as fixtures
+from tempest.services.identity.v2.json import token_client as v2_client
+from tempest.services.identity.v3.json import token_client as v3_client
+from tempest.tests import fake_identity
+# Note: eventually the auth module will move to tempest-lib, and so wil its
+# unit tests. *CredentialsTests will be imported from tempest-lib then.
+from tempest.tests import test_credentials as test_creds
+
+
+class ConfiguredV2CredentialsTests(test_creds.CredentialsTests):
+ attributes = {
+ 'username': 'fake_username',
+ 'password': 'fake_password',
+ 'tenant_name': 'fake_tenant_name'
+ }
+
+ identity_response = fake_identity._fake_v2_response
+ credentials_class = auth.KeystoneV2Credentials
+ tokenclient_class = v2_client.TokenClientJSON
+ identity_version = 'v2'
+
+ def setUp(self):
+ super(ConfiguredV2CredentialsTests, self).setUp()
+ self.stubs.Set(self.tokenclient_class, 'raw_request',
+ self.identity_response)
+
+ def _verify_credentials(self, credentials_class, filled=True,
+ identity_version=None):
+ for ctype in cred_provider.CREDENTIAL_TYPES:
+ if identity_version is None:
+ creds = cred_provider.get_configured_credentials(
+ credential_type=ctype, fill_in=filled)
+ else:
+ creds = cred_provider.get_configured_credentials(
+ credential_type=ctype, fill_in=filled,
+ identity_version=identity_version)
+ self._check(creds, credentials_class, filled)
+
+ def test_get_configured_credentials(self):
+ self.useFixture(fixtures.LockFixture('auth_version'))
+ self._verify_credentials(credentials_class=self.credentials_class)
+
+ def test_get_configured_credentials_unfilled(self):
+ self.useFixture(fixtures.LockFixture('auth_version'))
+ self._verify_credentials(credentials_class=self.credentials_class,
+ filled=False)
+
+ def test_get_configured_credentials_version(self):
+ # version specified and not loaded from config
+ self.useFixture(fixtures.LockFixture('auth_version'))
+ self._verify_credentials(credentials_class=self.credentials_class,
+ identity_version=self.identity_version)
+
+ def test_is_valid(self):
+ creds = self._get_credentials()
+ self.assertTrue(creds.is_valid())
+
+
+class ConfiguredV3CredentialsTests(ConfiguredV2CredentialsTests):
+ attributes = {
+ 'username': 'fake_username',
+ 'password': 'fake_password',
+ 'project_name': 'fake_project_name',
+ 'user_domain_name': 'fake_domain_name'
+ }
+
+ credentials_class = auth.KeystoneV3Credentials
+ identity_response = fake_identity._fake_v3_response
+ tokenclient_class = v3_client.V3TokenClientJSON
+ identity_version = 'v3'
+
+ def setUp(self):
+ super(ConfiguredV3CredentialsTests, self).setUp()
+ # Additional config items reset by cfg fixture after each test
+ cfg.CONF.set_default('auth_version', 'v3', group='identity')
+ # Identity group items
+ for prefix in ['', 'alt_', 'admin_']:
+ cfg.CONF.set_default(prefix + 'domain_name', 'fake_domain_name',
+ group='identity')
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
index 57217e3..2656a47 100644
--- a/tempest/tests/common/test_custom_matchers.py
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -63,4 +63,4 @@
" b: expected 2, actual None\n",
{'a': 1, 'b': None, 'foo': 1},
matches_matcher)
- ]
\ No newline at end of file
+ ]
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index 2b31d6b..9bb58b0 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -43,8 +43,20 @@
from tempest.services.compute.json import tenant_usages_client
from tempest.services.compute.json import volumes_extensions_client \
as compute_volumes_extensions_client
+from tempest.services.data_processing.v1_1 import data_processing_client
from tempest.services.database.json import flavors_client as db_flavor_client
from tempest.services.database.json import versions_client as db_version_client
+from tempest.services.identity.v2.json import identity_client as \
+ identity_v2_identity_client
+from tempest.services.identity.v3.json import credentials_client
+from tempest.services.identity.v3.json import endpoints_client
+from tempest.services.identity.v3.json import identity_client as \
+ identity_v3_identity_client
+from tempest.services.identity.v3.json import policy_client
+from tempest.services.identity.v3.json import region_client
+from tempest.services.identity.v3.json import service_client
+from tempest.services.image.v1.json import image_client
+from tempest.services.image.v2.json import image_client as image_v2_client
from tempest.services.messaging.json import messaging_client
from tempest.services.network.json import network_client
from tempest.services.object_storage import account_client
@@ -117,6 +129,7 @@
services_client.ServicesClientJSON,
tenant_usages_client.TenantUsagesClientJSON,
compute_volumes_extensions_client.VolumesExtensionsClientJSON,
+ data_processing_client.DataProcessingClient,
db_flavor_client.DatabaseFlavorsClientJSON,
db_version_client.DatabaseVersionsClientJSON,
messaging_client.MessagingClientJSON,
@@ -146,6 +159,15 @@
volume_v2_qos_client.QosSpecsV2ClientJSON,
volume_v2_snapshots_client.SnapshotsV2ClientJSON,
volume_v2_volumes_client.VolumesV2ClientJSON,
+ identity_v2_identity_client.IdentityClientJSON,
+ credentials_client.CredentialsClientJSON,
+ endpoints_client.EndPointClientJSON,
+ identity_v3_identity_client.IdentityV3ClientJSON,
+ policy_client.PolicyClientJSON,
+ region_client.RegionClientJSON,
+ service_client.ServiceClientJSON,
+ image_client.ImageClientJSON,
+ image_v2_client.ImageClientV2JSON
]
for client in test_clients:
diff --git a/tempest/tests/fake_identity.py b/tempest/tests/fake_identity.py
index 97098e1..ad78f85 100644
--- a/tempest/tests/fake_identity.py
+++ b/tempest/tests/fake_identity.py
@@ -17,6 +17,7 @@
import httplib2
+FAKE_AUTH_URL = 'http://fake_uri.com/auth'
TOKEN = "fake_token"
ALT_TOKEN = "alt_fake_token"
diff --git a/tempest/tests/negative/test_negative_auto_test.py b/tempest/tests/negative/test_negative_auto_test.py
index fb1da43..7a127cd 100644
--- a/tempest/tests/negative/test_negative_auto_test.py
+++ b/tempest/tests/negative/test_negative_auto_test.py
@@ -21,7 +21,6 @@
class TestNegativeAutoTest(base.TestCase):
# Fake entries
- _interface = 'json'
_service = 'compute'
fake_input_desc = {"name": "list-flavors-with-detail",
diff --git a/tempest/tests/test_auth.py b/tempest/tests/test_auth.py
index 90bb8a7..f54ff4f 100644
--- a/tempest/tests/test_auth.py
+++ b/tempest/tests/test_auth.py
@@ -21,7 +21,7 @@
from tempest import auth
from tempest import config
from tempest import exceptions
-from tempest.services.identity.json import token_client as v2_client
+from tempest.services.identity.v2.json import token_client as v2_client
from tempest.services.identity.v3.json import token_client as v3_client
from tempest.tests import base
from tempest.tests import fake_config
@@ -30,11 +30,7 @@
from tempest.tests import fake_identity
-def fake_get_default_credentials(credential_type, fill_in=True):
- return fake_credentials.FakeCredentials()
-
-
-def fake_get_credentials(credential_type=None, fill_in=True, **kwargs):
+def fake_get_credentials(fill_in=True, identity_version='v2', **kwargs):
return fake_credentials.FakeCredentials()
@@ -42,11 +38,11 @@
_auth_provider_class = None
credentials = fake_credentials.FakeCredentials()
- def _auth(self, credentials, **params):
+ def _auth(self, credentials, auth_url, **params):
"""
returns auth method according to keystone
"""
- return self._auth_provider_class(credentials, **params)
+ return self._auth_provider_class(credentials, auth_url, **params)
def setUp(self):
super(BaseAuthTestsSetUp, self).setUp()
@@ -54,9 +50,8 @@
self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
- self.stubs.Set(auth, 'get_default_credentials',
- fake_get_default_credentials)
- self.auth_provider = self._auth(self.credentials)
+ self.auth_provider = self._auth(self.credentials,
+ fake_identity.FAKE_AUTH_URL)
class TestBaseAuthProvider(BaseAuthTestsSetUp):
@@ -84,14 +79,15 @@
_auth_provider_class = FakeAuthProviderImpl
+ def _auth(self, credentials, auth_url, **params):
+ """
+ returns auth method according to keystone
+ """
+ return self._auth_provider_class(credentials, **params)
+
def test_check_credentials_bad_type(self):
self.assertFalse(self.auth_provider.check_credentials([]))
- def test_instantiate_with_dict(self):
- # Dict credentials are only supported for backward compatibility
- auth_provider = self._auth(credentials={})
- self.assertIsInstance(auth_provider.credentials, auth.Credentials)
-
def test_auth_data_property_when_cache_exists(self):
self.auth_provider.cache = 'foo'
self.useFixture(mockpatch.PatchObject(self.auth_provider,
diff --git a/tempest/tests/test_credentials.py b/tempest/tests/test_credentials.py
index 6e447d6..350b190 100644
--- a/tempest/tests/test_credentials.py
+++ b/tempest/tests/test_credentials.py
@@ -15,13 +15,11 @@
import copy
-from oslo.config import cfg
-
from tempest import auth
from tempest.common import tempest_fixtures as fixtures
from tempest import config
from tempest import exceptions
-from tempest.services.identity.json import token_client as v2_client
+from tempest.services.identity.v2.json import token_client as v2_client
from tempest.services.identity.v3.json import token_client as v3_client
from tempest.tests import base
from tempest.tests import fake_config
@@ -37,6 +35,18 @@
attributes = self.attributes
return self.credentials_class(**attributes)
+ def _check(self, credentials, credentials_class, filled):
+ # Check the right version of credentials has been returned
+ self.assertIsInstance(credentials, credentials_class)
+ # Check the id attributes are filled in
+ attributes = [x for x in credentials.ATTRIBUTES if (
+ '_id' in x and x != 'domain_id')]
+ for attr in attributes:
+ if filled:
+ self.assertIsNotNone(getattr(credentials, attr))
+ else:
+ self.assertIsNone(getattr(credentials, attr))
+
def setUp(self):
super(CredentialsTests, self).setUp()
self.useFixture(fake_config.ConfigFixture())
@@ -51,18 +61,6 @@
self._get_credentials,
attributes=dict(invalid='fake'))
- def test_default(self):
- self.useFixture(fixtures.LockFixture('auth_version'))
- for ctype in self.credentials_class.TYPES:
- self.assertRaises(NotImplementedError,
- self.credentials_class.get_default,
- credentials_type=ctype)
-
- def test_invalid_default(self):
- self.assertRaises(exceptions.InvalidCredentials,
- auth.Credentials.get_default,
- credentials_type='invalid_type')
-
def test_is_valid(self):
creds = self._get_credentials()
self.assertRaises(NotImplementedError, creds.is_valid)
@@ -78,39 +76,19 @@
identity_response = fake_identity._fake_v2_response
credentials_class = auth.KeystoneV2Credentials
tokenclient_class = v2_client.TokenClientJSON
+ identity_version = 'v2'
def setUp(self):
super(KeystoneV2CredentialsTests, self).setUp()
self.stubs.Set(self.tokenclient_class, 'raw_request',
self.identity_response)
- def _verify_credentials(self, credentials_class, filled=True,
- creds_dict=None):
-
- def _check(credentials):
- # Check the right version of credentials has been returned
- self.assertIsInstance(credentials, credentials_class)
- # Check the id attributes are filled in
- attributes = [x for x in credentials.ATTRIBUTES if (
- '_id' in x and x != 'domain_id')]
- for attr in attributes:
- if filled:
- self.assertIsNotNone(getattr(credentials, attr))
- else:
- self.assertIsNone(getattr(credentials, attr))
-
- if creds_dict is None:
- for ctype in auth.Credentials.TYPES:
- creds = auth.get_default_credentials(credential_type=ctype,
- fill_in=filled)
- _check(creds)
- else:
- creds = auth.get_credentials(fill_in=filled, **creds_dict)
- _check(creds)
-
- def test_get_default_credentials(self):
- self.useFixture(fixtures.LockFixture('auth_version'))
- self._verify_credentials(credentials_class=self.credentials_class)
+ def _verify_credentials(self, credentials_class, creds_dict, filled=True):
+ creds = auth.get_credentials(fake_identity.FAKE_AUTH_URL,
+ fill_in=filled,
+ identity_version=self.identity_version,
+ **creds_dict)
+ self._check(creds, credentials_class, filled)
def test_get_credentials(self):
self.useFixture(fixtures.LockFixture('auth_version'))
@@ -120,8 +98,8 @@
def test_get_credentials_not_filled(self):
self.useFixture(fixtures.LockFixture('auth_version'))
self._verify_credentials(credentials_class=self.credentials_class,
- filled=False,
- creds_dict=self.attributes)
+ creds_dict=self.attributes,
+ filled=False)
def test_is_valid(self):
creds = self._get_credentials()
@@ -144,15 +122,6 @@
# credential requirements
self._test_is_not_valid('tenant_name')
- def test_default(self):
- self.useFixture(fixtures.LockFixture('auth_version'))
- for ctype in self.credentials_class.TYPES:
- creds = self.credentials_class.get_default(credentials_type=ctype)
- for attr in self.attributes.keys():
- # Default configuration values related to credentials
- # are defined as fake_* in fake_config.py
- self.assertEqual(getattr(creds, attr), 'fake_' + attr)
-
def test_reset_all_attributes(self):
creds = self._get_credentials()
initial_creds = copy.deepcopy(creds)
@@ -189,28 +158,7 @@
credentials_class = auth.KeystoneV3Credentials
identity_response = fake_identity._fake_v3_response
tokenclient_class = v3_client.V3TokenClientJSON
-
- def setUp(self):
- super(KeystoneV3CredentialsTests, self).setUp()
- # Additional config items reset by cfg fixture after each test
- cfg.CONF.set_default('auth_version', 'v3', group='identity')
- # Identity group items
- for prefix in ['', 'alt_', 'admin_']:
- cfg.CONF.set_default(prefix + 'domain_name', 'fake_domain_name',
- group='identity')
-
- def test_default(self):
- self.useFixture(fixtures.LockFixture('auth_version'))
- for ctype in self.credentials_class.TYPES:
- creds = self.credentials_class.get_default(credentials_type=ctype)
- for attr in self.attributes.keys():
- if attr == 'project_name':
- config_value = 'fake_tenant_name'
- elif attr == 'user_domain_name':
- config_value = 'fake_domain_name'
- else:
- config_value = 'fake_' + attr
- self.assertEqual(getattr(creds, attr), config_value)
+ identity_version = 'v3'
def test_is_not_valid(self):
# NOTE(mtreinish) For a Keystone V3 credential object a project name
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index 1f1835e..5149ba6 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import uuid
import mock
from oslo.config import cfg
@@ -64,6 +65,43 @@
self._test_attr_helper(expected_attrs=['foo'], type=['foo', 'foo'])
+class TestIdempotentIdDecorator(BaseDecoratorsTest):
+
+ def _test_helper(self, _id, **decorator_args):
+ @test.idempotent_id(_id)
+ def foo():
+ """Docstring"""
+ pass
+
+ return foo
+
+ def _test_helper_without_doc(self, _id, **decorator_args):
+ @test.idempotent_id(_id)
+ def foo():
+ pass
+
+ return foo
+
+ def test_positive(self):
+ _id = str(uuid.uuid4())
+ foo = self._test_helper(_id)
+ self.assertIn('id-%s' % _id, getattr(foo, '__testtools_attrs'))
+ self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
+
+ def test_positive_without_doc(self):
+ _id = str(uuid.uuid4())
+ foo = self._test_helper_without_doc(_id)
+ self.assertTrue(foo.__doc__.startswith('Test idempotent id: %s' % _id))
+
+ def test_idempotent_id_not_str(self):
+ _id = 42
+ self.assertRaises(TypeError, self._test_helper, _id)
+
+ def test_idempotent_id_not_valid_uuid(self):
+ _id = '42'
+ self.assertRaises(ValueError, self._test_helper, _id)
+
+
class TestServicesDecorator(BaseDecoratorsTest):
def _test_services_helper(self, *decorator_args):
class TestFoo(test.BaseTestCase):
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 6c80496..ab76a93 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -20,8 +20,9 @@
from tempest import config
from tempest import exceptions
from tempest.openstack.common.fixture import mockpatch
-from tempest.services.identity.json import identity_client as json_iden_client
-from tempest.services.identity.json import token_client as json_token_client
+from tempest.services.identity.v2.json import identity_client as \
+ json_iden_client
+from tempest.services.identity.v2.json import token_client as json_token_client
from tempest.services.network.json import network_client as json_network_client
from tempest.tests import base
from tempest.tests import fake_config
@@ -175,10 +176,10 @@
self._mock_list_roles('123456', 'admin')
iso_creds.get_admin_creds()
user_mock = self.patch(
- 'tempest.services.identity.json.identity_client.'
+ 'tempest.services.identity.v2.json.identity_client.'
'IdentityClientJSON.delete_user')
tenant_mock = self.patch(
- 'tempest.services.identity.json.identity_client.'
+ 'tempest.services.identity.v2.json.identity_client.'
'IdentityClientJSON.delete_tenant')
iso_creds.clear_isolated_creds()
# Verify user delete calls
@@ -293,9 +294,9 @@
router_fix = self._mock_router_create('123456', 'fake_admin_router')
self._mock_list_roles('123456', 'admin')
iso_creds.get_admin_creds()
- self.patch('tempest.services.identity.json.identity_client.'
+ self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClientJSON.delete_user')
- self.patch('tempest.services.identity.json.identity_client.'
+ self.patch('tempest.services.identity.v2.json.identity_client.'
'IdentityClientJSON.delete_tenant')
net = mock.patch.object(iso_creds.network_admin_client,
'delete_network')
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index edd9de1..5b2ed70 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -201,10 +201,14 @@
raise cls.skipException("The EC2 API is not available")
@classmethod
+ def setup_credentials(cls):
+ super(BotoTestCase, cls).setup_credentials()
+ cls.os = cls.get_client_manager()
+
+ @classmethod
def resource_setup(cls):
super(BotoTestCase, cls).resource_setup()
cls.conclusion = decision_maker()
- cls.os = cls.get_client_manager()
# The trash contains cleanup functions and paramaters in tuples
# (function, *args, **kwargs)
cls._resource_trash_bin = {}
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 707590e..39767a4 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -18,6 +18,7 @@
from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
from tempest.thirdparty.boto.utils import s3
from tempest.thirdparty.boto.utils import wait
@@ -30,13 +31,17 @@
class InstanceRunTest(boto_test.BotoTestCase):
@classmethod
+ def setup_clients(cls):
+ super(InstanceRunTest, cls).setup_clients()
+ cls.s3_client = cls.os.s3_client
+ cls.ec2_client = cls.os.ec2api_client
+
+ @classmethod
def resource_setup(cls):
super(InstanceRunTest, cls).resource_setup()
if not cls.conclusion['A_I_IMAGES_READY']:
raise cls.skipException("".join(("EC2 ", cls.__name__,
": requires ami/aki/ari manifest")))
- cls.s3_client = cls.os.s3_client
- cls.ec2_client = cls.os.ec2api_client
cls.zone = CONF.boto.aws_zone
cls.materials_path = CONF.boto.s3_materials_path
ami_manifest = CONF.boto.ami_manifest
@@ -87,6 +92,7 @@
self.assertInstanceStateWait(instance, '_GONE')
self.cancelResourceCleanUp(rcuk)
+ @test.idempotent_id('c881fbb7-d56e-4054-9d76-1c3a60a207b0')
def test_run_idempotent_instances(self):
# EC2 run instances idempotently
@@ -119,6 +125,7 @@
self._terminate_reservation(reservation_1, rcuk_1)
self._terminate_reservation(reservation_2, rcuk_2)
+ @test.idempotent_id('2ea26a39-f96c-48fc-8374-5c10ec184c67')
def test_run_stop_terminate_instance(self):
# EC2 run, stop and terminate instance
image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -141,6 +148,7 @@
self._terminate_reservation(reservation, rcuk)
+ @test.idempotent_id('3d77225a-5cec-4e54-a017-9ebf11a266e6')
def test_run_stop_terminate_instance_with_tags(self):
# EC2 run, stop and terminate instance with tags
image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -193,6 +201,7 @@
self._terminate_reservation(reservation, rcuk)
+ @test.idempotent_id('252945b5-3294-4fda-ae21-928a42f63f76')
def test_run_terminate_instance(self):
# EC2 run, terminate immediately
image_ami = self.ec2_client.get_image(self.images["ami"]
@@ -205,6 +214,7 @@
instance.terminate()
self.assertInstanceStateWait(instance, '_GONE')
+ @test.idempotent_id('ab836c29-737b-4101-9fb9-87045eaf89e9')
def test_compute_with_volumes(self):
# EC2 1. integration test (not strict)
image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index be5db55..acf797a 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -14,6 +14,7 @@
# under the License.
from tempest.common.utils import data_utils
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
@@ -25,12 +26,17 @@
class EC2KeysTest(boto_test.BotoTestCase):
@classmethod
+ def setup_clients(cls):
+ super(EC2KeysTest, cls).setup_clients()
+ cls.client = cls.os.ec2api_client
+
+ @classmethod
def resource_setup(cls):
super(EC2KeysTest, cls).resource_setup()
- cls.client = cls.os.ec2api_client
cls.ec = cls.ec2_error_code
# TODO(afazekas): merge create, delete, get test cases
+ @test.idempotent_id('54236804-01b7-4cfe-a6f9-bce1340feec8')
def test_create_ec2_keypair(self):
# EC2 create KeyPair
key_name = data_utils.rand_name("keypair-")
@@ -39,6 +45,7 @@
self.assertTrue(compare_key_pairs(keypair,
self.client.get_key_pair(key_name)))
+ @test.idempotent_id('3283b898-f90c-4952-b238-3e42b8c3f34f')
def test_delete_ec2_keypair(self):
# EC2 delete KeyPair
key_name = data_utils.rand_name("keypair-")
@@ -46,6 +53,7 @@
self.client.delete_key_pair(key_name)
self.assertIsNone(self.client.get_key_pair(key_name))
+ @test.idempotent_id('fd89bd26-4d4d-4cf3-a303-65dd9158fcdc')
def test_get_ec2_keypair(self):
# EC2 get KeyPair
key_name = data_utils.rand_name("keypair-")
@@ -54,6 +62,7 @@
self.assertTrue(compare_key_pairs(keypair,
self.client.get_key_pair(key_name)))
+ @test.idempotent_id('daa73da1-e11c-4558-8d76-a716be79a401')
def test_duplicate_ec2_keypair(self):
# EC2 duplicate KeyPair
key_name = data_utils.rand_name("keypair-")
diff --git a/tempest/thirdparty/boto/test_ec2_network.py b/tempest/thirdparty/boto/test_ec2_network.py
index 132a5a8..ce20156 100644
--- a/tempest/thirdparty/boto/test_ec2_network.py
+++ b/tempest/thirdparty/boto/test_ec2_network.py
@@ -13,17 +13,19 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
class EC2NetworkTest(boto_test.BotoTestCase):
@classmethod
- def resource_setup(cls):
- super(EC2NetworkTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(EC2NetworkTest, cls).setup_clients()
cls.ec2_client = cls.os.ec2api_client
# Note(afazekas): these tests for things duable without an instance
+ @test.idempotent_id('48b912af-9403-4b4f-aa69-fa76d690a81f')
def test_disassociate_not_associated_floating_ip(self):
# EC2 disassociate not associated floating ip
ec2_codes = self.ec2_error_code
diff --git a/tempest/thirdparty/boto/test_ec2_security_groups.py b/tempest/thirdparty/boto/test_ec2_security_groups.py
index fb3d32b..7f9568b 100644
--- a/tempest/thirdparty/boto/test_ec2_security_groups.py
+++ b/tempest/thirdparty/boto/test_ec2_security_groups.py
@@ -14,16 +14,18 @@
# under the License.
from tempest.common.utils import data_utils
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
class EC2SecurityGroupTest(boto_test.BotoTestCase):
@classmethod
- def resource_setup(cls):
- super(EC2SecurityGroupTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(EC2SecurityGroupTest, cls).setup_clients()
cls.client = cls.os.ec2api_client
+ @test.idempotent_id('519b566e-0c38-4629-905e-7d6b6355f524')
def test_create_authorize_security_group(self):
# EC2 Create, authorize/revoke security group
group_name = data_utils.rand_name("securty_group-")
diff --git a/tempest/thirdparty/boto/test_ec2_volumes.py b/tempest/thirdparty/boto/test_ec2_volumes.py
index 9cee8a4..318e8e3 100644
--- a/tempest/thirdparty/boto/test_ec2_volumes.py
+++ b/tempest/thirdparty/boto/test_ec2_volumes.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.openstack.common import log as logging
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
CONF = config.CONF
@@ -29,16 +30,23 @@
class EC2VolumesTest(boto_test.BotoTestCase):
@classmethod
- def resource_setup(cls):
- super(EC2VolumesTest, cls).resource_setup()
-
+ def skip_checks(cls):
+ super(EC2VolumesTest, 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(EC2VolumesTest, cls).setup_clients()
cls.client = cls.os.ec2api_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(EC2VolumesTest, cls).resource_setup()
cls.zone = CONF.boto.aws_zone
+ @test.idempotent_id('663f0077-c743-48ad-8ae0-46821cbc0918')
def test_create_get_delete(self):
# EC2 Create, get, delete Volume
volume = self.client.create_volume(1, self.zone)
@@ -51,6 +59,7 @@
self.client.delete_volume(volume.id)
self.cancelResourceCleanUp(cuk)
+ @test.idempotent_id('c6b60d7a-1af7-4f8e-af21-d539d9496149')
def test_create_volume_from_snapshot(self):
# EC2 Create volume from snapshot
volume = self.client.create_volume(1, self.zone)
diff --git a/tempest/thirdparty/boto/test_s3_buckets.py b/tempest/thirdparty/boto/test_s3_buckets.py
index 342fc0e..bf04803 100644
--- a/tempest/thirdparty/boto/test_s3_buckets.py
+++ b/tempest/thirdparty/boto/test_s3_buckets.py
@@ -14,16 +14,18 @@
# under the License.
from tempest.common.utils import data_utils
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
class S3BucketsTest(boto_test.BotoTestCase):
@classmethod
- def resource_setup(cls):
- super(S3BucketsTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(S3BucketsTest, cls).setup_clients()
cls.client = cls.os.s3_client
+ @test.idempotent_id('4678525d-8da0-4518-81c1-f1f67d595b00')
def test_create_and_get_delete_bucket(self):
# S3 Create, get and delete bucket
bucket_name = data_utils.rand_name("s3bucket-")
diff --git a/tempest/thirdparty/boto/test_s3_ec2_images.py b/tempest/thirdparty/boto/test_s3_ec2_images.py
index f5dec95..21ea984 100644
--- a/tempest/thirdparty/boto/test_s3_ec2_images.py
+++ b/tempest/thirdparty/boto/test_s3_ec2_images.py
@@ -17,6 +17,7 @@
from tempest.common.utils import data_utils
from tempest import config
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
from tempest.thirdparty.boto.utils import s3
@@ -26,13 +27,17 @@
class S3ImagesTest(boto_test.BotoTestCase):
@classmethod
+ def setup_clients(cls):
+ super(S3ImagesTest, cls).setup_clients()
+ cls.s3_client = cls.os.s3_client
+ cls.images_client = cls.os.ec2api_client
+
+ @classmethod
def resource_setup(cls):
super(S3ImagesTest, cls).resource_setup()
if not cls.conclusion['A_I_IMAGES_READY']:
raise cls.skipException("".join(("EC2 ", cls.__name__,
": requires ami/aki/ari manifest")))
- cls.s3_client = cls.os.s3_client
- cls.images_client = cls.os.ec2api_client
cls.materials_path = CONF.boto.s3_materials_path
cls.ami_manifest = CONF.boto.ami_manifest
cls.aki_manifest = CONF.boto.aki_manifest
@@ -47,6 +52,7 @@
cls.bucket_name)
s3.s3_upload_dir(bucket, cls.materials_path)
+ @test.idempotent_id('f9d360a5-0188-4c77-9db2-4c34c28d12a5')
def test_register_get_deregister_ami_image(self):
# Register and deregister ami image
image = {"name": data_utils.rand_name("ami-name-"),
@@ -70,6 +76,7 @@
self.images_client.get_all_images()))
self.cancelResourceCleanUp(image["cleanUp"])
+ @test.idempotent_id('42cca5b0-453b-4618-b99f-dbc039db426f')
def test_register_get_deregister_aki_image(self):
# Register and deregister aki image
image = {"name": data_utils.rand_name("aki-name-"),
@@ -93,6 +100,7 @@
self.images_client.get_all_images()))
self.cancelResourceCleanUp(image["cleanUp"])
+ @test.idempotent_id('1359e860-841c-43bb-80f3-bb389cbfd81d')
def test_register_get_deregister_ari_image(self):
# Register and deregister ari image
image = {"name": data_utils.rand_name("ari-name-"),
diff --git a/tempest/thirdparty/boto/test_s3_objects.py b/tempest/thirdparty/boto/test_s3_objects.py
index 43774c2..2d8152d 100644
--- a/tempest/thirdparty/boto/test_s3_objects.py
+++ b/tempest/thirdparty/boto/test_s3_objects.py
@@ -18,16 +18,18 @@
import boto.s3.key
from tempest.common.utils import data_utils
+from tempest import test
from tempest.thirdparty.boto import test as boto_test
class S3BucketsTest(boto_test.BotoTestCase):
@classmethod
- def resource_setup(cls):
- super(S3BucketsTest, cls).resource_setup()
+ def setup_clients(cls):
+ super(S3BucketsTest, cls).setup_clients()
cls.client = cls.os.s3_client
+ @test.idempotent_id('4eea567a-b46a-405b-a475-6097e1faebde')
def test_create_get_delete_object(self):
# S3 Create, get and delete object
bucket_name = data_utils.rand_name("s3bucket-")
diff --git a/test-requirements.txt b/test-requirements.txt
index 6eefeee..6a9111e 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
-hacking>=0.9.2,<0.10
+hacking<0.11,>=0.10.0
# needed for doc build
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
python-subunit>=0.0.18
diff --git a/tools/check_uuid.py b/tools/check_uuid.py
new file mode 100644
index 0000000..541e6c3
--- /dev/null
+++ b/tools/check_uuid.py
@@ -0,0 +1,354 @@
+# Copyright 2014 Mirantis, Inc.
+#
+# 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 argparse
+import ast
+import importlib
+import inspect
+import os
+import sys
+import unittest
+import urllib
+import uuid
+
+DECORATOR_MODULE = 'test'
+DECORATOR_NAME = 'idempotent_id'
+DECORATOR_IMPORT = 'tempest.%s' % DECORATOR_MODULE
+IMPORT_LINE = 'from tempest import %s' % DECORATOR_MODULE
+DECORATOR_TEMPLATE = "@%s.%s('%%s')" % (DECORATOR_MODULE,
+ DECORATOR_NAME)
+UNIT_TESTS_EXCLUDE = 'tempest.tests'
+
+
+class SourcePatcher(object):
+
+ """"Lazy patcher for python source files"""
+
+ def __init__(self):
+ self.source_files = None
+ self.patches = None
+ self.clear()
+
+ def clear(self):
+ """Clear inner state"""
+ self.source_files = {}
+ self.patches = {}
+
+ @staticmethod
+ def _quote(s):
+ return urllib.quote(s)
+
+ @staticmethod
+ def _unquote(s):
+ return urllib.unquote(s)
+
+ def add_patch(self, filename, patch, line_no):
+ """Add lazy patch"""
+ if filename not in self.source_files:
+ with open(filename) as f:
+ self.source_files[filename] = self._quote(f.read())
+ patch_id = str(uuid.uuid4())
+ if not patch.endswith('\n'):
+ patch += '\n'
+ self.patches[patch_id] = self._quote(patch)
+ lines = self.source_files[filename].split(self._quote('\n'))
+ lines[line_no - 1] = ''.join(('{%s:s}' % patch_id, lines[line_no - 1]))
+ self.source_files[filename] = self._quote('\n').join(lines)
+
+ def _save_changes(self, filename, source):
+ print('%s fixed' % filename)
+ with open(filename, 'w') as f:
+ f.write(source)
+
+ def apply_patches(self):
+ """Apply all patches"""
+ for filename in self.source_files:
+ patched_source = self._unquote(
+ self.source_files[filename].format(**self.patches)
+ )
+ self._save_changes(filename, patched_source)
+ self.clear()
+
+
+class TestChecker(object):
+
+ def __init__(self, package):
+ self.package = package
+ self.base_path = os.path.abspath(os.path.dirname(package.__file__))
+
+ def _path_to_package(self, path):
+ relative_path = path[len(self.base_path) + 1:]
+ if relative_path:
+ return '.'.join((self.package.__name__,) +
+ tuple(relative_path.split('/')))
+ else:
+ return self.package.__name__
+
+ def _modules_search(self):
+ """Recursive search for python modules in base package"""
+ modules = []
+ for root, dirs, files in os.walk(self.base_path):
+ if not os.path.exists(os.path.join(root, '__init__.py')):
+ continue
+ root_package = self._path_to_package(root)
+ for item in files:
+ if item.endswith('.py'):
+ module_name = '.'.join((root_package,
+ os.path.splitext(item)[0]))
+ if not module_name.startswith(UNIT_TESTS_EXCLUDE):
+ modules.append(module_name)
+ return modules
+
+ @staticmethod
+ def _get_idempotent_id(test_node):
+ """
+ Return key-value dict with all metadata from @test.idempotent_id
+ decorators for test method
+ """
+ idempotent_id = None
+ for decorator in test_node.decorator_list:
+ if (hasattr(decorator, 'func') and
+ decorator.func.attr == DECORATOR_NAME and
+ decorator.func.value.id == DECORATOR_MODULE):
+ for arg in decorator.args:
+ idempotent_id = ast.literal_eval(arg)
+ return idempotent_id
+
+ @staticmethod
+ def _is_decorator(line):
+ return line.strip().startswith('@')
+
+ @staticmethod
+ def _is_def(line):
+ return line.strip().startswith('def ')
+
+ def _add_uuid_to_test(self, patcher, test_node, source_path):
+ with open(source_path) as src:
+ src_lines = src.read().split('\n')
+ lineno = test_node.lineno
+ insert_position = lineno
+ while True:
+ if (self._is_def(src_lines[lineno - 1]) or
+ (self._is_decorator(src_lines[lineno - 1]) and
+ (DECORATOR_TEMPLATE.split('(')[0] <=
+ src_lines[lineno - 1].strip().split('(')[0]))):
+ insert_position = lineno
+ break
+ lineno += 1
+ patcher.add_patch(
+ source_path,
+ ' ' * test_node.col_offset + DECORATOR_TEMPLATE % uuid.uuid4(),
+ insert_position
+ )
+
+ @staticmethod
+ def _is_test_case(module, node):
+ if (node.__class__ is ast.ClassDef and
+ hasattr(module, node.name) and
+ inspect.isclass(getattr(module, node.name))):
+ return issubclass(getattr(module, node.name), unittest.TestCase)
+
+ @staticmethod
+ def _is_test_method(node):
+ return (node.__class__ is ast.FunctionDef
+ and node.name.startswith('test_'))
+
+ @staticmethod
+ def _next_node(body, node):
+ if body.index(node) < len(body):
+ return body[body.index(node) + 1]
+
+ @staticmethod
+ def _import_name(node):
+ if type(node) == ast.Import:
+ return node.names[0].name
+ elif type(node) == ast.ImportFrom:
+ return '%s.%s' % (node.module, node.names[0].name)
+
+ def _add_import_for_test_uuid(self, patcher, src_parsed, source_path):
+ with open(source_path) as f:
+ src_lines = f.read().split('\n')
+ line_no = 0
+ tempest_imports = [node for node in src_parsed.body
+ if self._import_name(node) and
+ 'tempest.' in self._import_name(node)]
+ if not tempest_imports:
+ import_snippet = '\n'.join(('', IMPORT_LINE, ''))
+ else:
+ for node in tempest_imports:
+ if self._import_name(node) < DECORATOR_IMPORT:
+ continue
+ else:
+ line_no = node.lineno
+ import_snippet = IMPORT_LINE
+ break
+ else:
+ line_no = tempest_imports[-1].lineno
+ while True:
+ if (not src_lines[line_no - 1] or
+ getattr(self._next_node(src_parsed.body,
+ tempest_imports[-1]),
+ 'lineno') == line_no or
+ line_no == len(src_lines)):
+ break
+ line_no += 1
+ import_snippet = '\n'.join((IMPORT_LINE, ''))
+ patcher.add_patch(source_path, import_snippet, line_no)
+
+ def get_tests(self):
+ """Get test methods with sources from base package with metadata"""
+ tests = {}
+ for module_name in self._modules_search():
+ tests[module_name] = {}
+ module = importlib.import_module(module_name)
+ source_path = '.'.join(
+ (os.path.splitext(module.__file__)[0], 'py')
+ )
+ with open(source_path, 'r') as f:
+ source = f.read()
+ tests[module_name]['source_path'] = source_path
+ tests[module_name]['tests'] = {}
+ source_parsed = ast.parse(source)
+ tests[module_name]['ast'] = source_parsed
+ tests[module_name]['import_valid'] = (
+ hasattr(module, DECORATOR_MODULE) and
+ inspect.ismodule(getattr(module, DECORATOR_MODULE))
+ )
+ test_cases = (node for node in source_parsed.body
+ if self._is_test_case(module, node))
+ for node in test_cases:
+ for subnode in filter(self._is_test_method, node.body):
+ test_name = '%s.%s' % (node.name, subnode.name)
+ tests[module_name]['tests'][test_name] = subnode
+ return tests
+
+ @staticmethod
+ def _filter_tests(function, tests):
+ """Filter tests with condition 'function(test_node) == True'"""
+ result = {}
+ for module_name in tests:
+ for test_name in tests[module_name]['tests']:
+ if function(module_name, test_name, tests):
+ if module_name not in result:
+ result[module_name] = {
+ 'ast': tests[module_name]['ast'],
+ 'source_path': tests[module_name]['source_path'],
+ 'import_valid': tests[module_name]['import_valid'],
+ 'tests': {}
+ }
+ result[module_name]['tests'][test_name] = \
+ tests[module_name]['tests'][test_name]
+ return result
+
+ def find_untagged(self, tests):
+ """Filter all tests without uuid in metadata"""
+ def check_uuid_in_meta(module_name, test_name, tests):
+ idempotent_id = self._get_idempotent_id(
+ tests[module_name]['tests'][test_name])
+ return not idempotent_id
+ return self._filter_tests(check_uuid_in_meta, tests)
+
+ def report_collisions(self, tests):
+ """Reports collisions if there are any. Returns true if
+ collisions exist.
+ """
+ uuids = {}
+
+ def report(module_name, test_name, tests):
+ test_uuid = self._get_idempotent_id(
+ tests[module_name]['tests'][test_name])
+ if not test_uuid:
+ return
+ if test_uuid in uuids:
+ error_str = "%s:%s\n uuid %s collision: %s<->%s\n%s:%s\n" % (
+ tests[module_name]['source_path'],
+ tests[module_name]['tests'][test_name].lineno,
+ test_uuid,
+ test_name,
+ uuids[test_uuid]['test_name'],
+ uuids[test_uuid]['source_path'],
+ uuids[test_uuid]['test_node'].lineno,
+ )
+ print(error_str)
+ return True
+ else:
+ uuids[test_uuid] = {
+ 'module': module_name,
+ 'test_name': test_name,
+ 'test_node': tests[module_name]['tests'][test_name],
+ 'source_path': tests[module_name]['source_path']
+ }
+ return bool(self._filter_tests(report, tests))
+
+ def report_untagged(self, tests):
+ """Reports untagged tests if there are any. Returns true if
+ untagged tests exist.
+ """
+ def report(module_name, test_name, tests):
+ error_str = "%s:%s\nmissing @test.idempotent_id('...')\n%s\n" % (
+ tests[module_name]['source_path'],
+ tests[module_name]['tests'][test_name].lineno,
+ test_name
+ )
+ print(error_str)
+ return True
+ return bool(self._filter_tests(report, tests))
+
+ def fix_tests(self, tests):
+ """Add uuids to all tests specified in tests and
+ fix it in source files
+ """
+ patcher = SourcePatcher()
+ for module_name in tests:
+ add_import_once = True
+ for test_name in tests[module_name]['tests']:
+ if not tests[module_name]['import_valid'] and add_import_once:
+ self._add_import_for_test_uuid(
+ patcher,
+ tests[module_name]['ast'],
+ tests[module_name]['source_path']
+ )
+ add_import_once = False
+ self._add_uuid_to_test(
+ patcher, tests[module_name]['tests'][test_name],
+ tests[module_name]['source_path'])
+ patcher.apply_patches()
+
+
+def run():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--package', action='store', dest='package',
+ default='tempest', type=str,
+ help='Package with tests')
+ parser.add_argument('--fix', action='store_true', dest='fix_tests',
+ help='Attempt to fix tests without UUIDs')
+ args = parser.parse_args()
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+ pkg = importlib.import_module(args.package)
+ checker = TestChecker(pkg)
+ errors = False
+ tests = checker.get_tests()
+ untagged = checker.find_untagged(tests)
+ errors = checker.report_collisions(tests) or errors
+ if args.fix_tests and untagged:
+ checker.fix_tests(untagged)
+ else:
+ errors = checker.report_untagged(untagged) or errors
+ if errors:
+ sys.exit("@test.idempotent_id existence and uniqueness checks failed\n"
+ "Run 'tox -v -euuidgen' to automatically fix tests with\n"
+ "missing @test.idempotent_id decorators.")
+
+if __name__ == '__main__':
+ run()
diff --git a/tox.ini b/tox.ini
index 2e8b509..ef98e90 100644
--- a/tox.ini
+++ b/tox.ini
@@ -113,6 +113,11 @@
commands =
flake8 {posargs}
{toxinidir}/tools/config/check_uptodate.sh
+ python tools/check_uuid.py
+
+[testenv:uuidgen]
+commands =
+ python tools/check_uuid.py --fix
[hacking]
local-check-factory = tempest.hacking.checks.factory
@@ -120,11 +125,9 @@
[flake8]
# E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved. For further detail see https://review.openstack.org/#/c/36788/
-# H402 skipped because some docstrings aren't sentences
# E123 skipped because it is ignored by default in the default pep8
# E129 skipped because it is too limiting when combined with other rules
-# H305 skipped because it is inconsistent between python versions
-# Skipped because of new hacking 0.9: H405,H904
-ignore = E125,H402,E123,E129,H404,H405,H904,H305
+# Skipped because of new hacking 0.9: H405
+ignore = E125,E123,E129,H404,H405
show-source = True
exclude = .git,.venv,.tox,dist,doc,openstack,*egg