Merge "Scenario/manager.py: always wait when delete a cinder vol"
diff --git a/README.rst b/README.rst
index 71e185f..c859ddd 100644
--- a/README.rst
+++ b/README.rst
@@ -94,6 +94,45 @@
.. _testr: https://testrepository.readthedocs.org/en/latest/MANUAL.html
.. _ostestr: http://docs.openstack.org/developer/os-testr/
+Library
+-------
+Tempest exposes a library interface. This interface is a stable interface and
+should be backwards compatible (including backwards compatibility with the
+old tempest-lib package, with the exception of the import). If you plan to
+directly consume tempest in your project you should only import code from the
+tempest library interface, other pieces of tempest do not have the same
+stable interface and there are no guarantees on the Python API unless otherwise
+stated.
+
+For more details refer to the library documentation here: :ref:`library`
+
+Release Versioning
+------------------
+Tempest's released versions are broken into 2 sets of information. Depending on
+how you intend to consume tempest you might need
+
+The version is a set of 3 numbers:
+
+X.Y.Z
+
+While this is almost `semver`_ like, the way versioning is handled is slightly
+different:
+
+X is used to represent the supported OpenStack releases for tempest tests
+in-tree, and to signify major feature changes to tempest. It's a monotonically
+increasing integer where each version either indicates a new supported OpenStack
+release, the drop of support for an OpenStack release (which will coincide with
+the upstream stable branch going EOL), or a major feature lands (or is removed)
+from tempest.
+
+Y.Z is used to represent library interface changes. This is treated the same
+way as minor and patch versions from `semver`_ but only for the library
+interface. When Y is incremented we've added functionality to the library
+interface and when Z is incremented it's a bug fix release for the library.
+Also note that both Y and Z are reset to 0 at each increment of X.
+
+.. _semver: http://semver.org/
+
Configuration
-------------
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 32e6e51..17def1c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -11,6 +11,7 @@
HACKING
REVIEWING
plugin
+ library
------------
Field Guides
diff --git a/doc/source/library.rst b/doc/source/library.rst
new file mode 100644
index 0000000..64bd2c2
--- /dev/null
+++ b/doc/source/library.rst
@@ -0,0 +1,69 @@
+.. _library:
+
+Tempest Library Documentation
+=============================
+
+Tempest provides a stable library interface that provides external tools or
+test suites an interface for reusing pieces of tempest code. Any public
+interface that lives in tempest/lib in the tempest repo is treated as a stable
+public interface and it should be safe to external consume that. Every effort
+goes into maintaining backwards compatibility with any change. Just as with
+tempest-lib the library is self contained and doesn't have any dependency on
+other tempest internals outside of lib. (including no usage of tempest
+configuration)
+
+Stability
+---------
+Just as tempest-lib before it any code that lives in tempest/lib will be treated
+as a stable interface, nothing has changed in regards to interface stability.
+This means that any public interface under the tempest/lib directory is
+expected to be a stable interface suitable for public consumption. However, for
+any interfaces outside of tempest/lib in the tempest tree (unless otherwise
+noted) or any private interfaces the same stability guarantees don't apply.
+
+Adding Interfaces
+'''''''''''''''''
+When adding an interface to tempest/lib we have to make sure there are no
+dependencies on any pieces of tempest outside of tempest/lib. This means if
+for example there is a dependency on the configuration file we need remove that.
+The other aspect when adding an interface is to make sure it's really an
+interface ready for external consumption and something we want to commit to
+supporting.
+
+Making changes
+''''''''''''''
+When making changes to tempest/lib you have to be conscious of the effect of
+any changes on external consumers. If your proposed changeset will change the
+default behaviour of any interface, or make something which previously worked
+not after your change, then it is not acceptable. Every effort needs to go into
+preserving backwards compatibility in changes.
+
+Reviewing
+'''''''''
+When reviewing a proposed change to tempest/lib code we need to be careful to
+ensure that we don't break backwards compatibility. For patches that change
+existing interfaces we have to be careful to make sure we don't break any
+external consumers. Some common red flags are:
+
+ * a change to an existing API requires a change outside the library directory
+ where the interface is being consumed
+ * a unit test has to be significantly changed to make the proposed change pass
+
+Testing
+'''''''
+When adding a new interface to the library we need to at a minimum have unit
+test coverage. A proposed change to add an interface to tempest/lib that
+doesn't have unit tests shouldn't be accepted. Ideally these unit tests will
+provide sufficient coverage to ensure a stable interface moving forward.
+
+Current Library APIs
+--------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ library/cli
+ library/decorators
+ library/rest_client
+ library/utils
+ library/api_microversion_testing
diff --git a/doc/source/library/api_microversion_testing.rst b/doc/source/library/api_microversion_testing.rst
new file mode 100644
index 0000000..0d0b595
--- /dev/null
+++ b/doc/source/library/api_microversion_testing.rst
@@ -0,0 +1,29 @@
+.. _api_microversion_testing:
+
+API Microversion Testing Support in Temepst
+===========================================
+
+---------------------------------------------
+Framework to support API Microversion testing
+---------------------------------------------
+
+Many of the OpenStack components have implemented API microversions.
+It is important to tests those microversion in Tempest or external plugins.
+Tempest now provides stable interfaces to support to test the API microversions.
+Based on the microversion range coming from the combination of both configuration
+and each test case, APIs request will be made with selected microversion.
+
+This document explains the interfaces needed for microversion testing.
+
+
+The api_version_request module
+""""""""""""""""""""""""""""""
+
+.. automodule:: tempest.lib.common.api_version_request
+ :members:
+
+The api_version_utils module
+""""""""""""""""""""""""""""
+
+.. automodule:: tempest.lib.common.api_version_utils
+ :members:
diff --git a/doc/source/library/cli.rst b/doc/source/library/cli.rst
new file mode 100644
index 0000000..6bd7881
--- /dev/null
+++ b/doc/source/library/cli.rst
@@ -0,0 +1,18 @@
+.. _cli:
+
+CLI Testing Framework Usage
+===========================
+
+-------------------
+The cli.base module
+-------------------
+
+.. automodule:: tempest.lib.cli.base
+ :members:
+
+----------------------------
+The cli.output_parser module
+----------------------------
+
+.. automodule:: tempest.lib.cli.output_parser
+ :members:
diff --git a/doc/source/library/decorators.rst b/doc/source/library/decorators.rst
new file mode 100644
index 0000000..a173967
--- /dev/null
+++ b/doc/source/library/decorators.rst
@@ -0,0 +1,13 @@
+.. _decorators:
+
+Decorators Usage Guide
+======================
+
+---------------------
+The decorators module
+---------------------
+
+.. automodule:: tempest.lib.decorators
+ :members:
+
+
diff --git a/doc/source/library/rest_client.rst b/doc/source/library/rest_client.rst
new file mode 100644
index 0000000..3045694
--- /dev/null
+++ b/doc/source/library/rest_client.rst
@@ -0,0 +1,11 @@
+.. _rest_client:
+
+Rest Client Usage
+=================
+
+----------------------
+The rest_client module
+----------------------
+
+.. automodule:: tempest.lib.common.rest_client
+ :members:
diff --git a/doc/source/library/utils.rst b/doc/source/library/utils.rst
new file mode 100644
index 0000000..bc2f79b
--- /dev/null
+++ b/doc/source/library/utils.rst
@@ -0,0 +1,11 @@
+.. _utils:
+
+Utils Usage
+===========
+
+---------------
+The misc module
+---------------
+
+.. automodule:: tempest.lib.common.utils.misc
+ :members:
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index 29653a6..2622c22 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -55,6 +55,37 @@
tempest.test_plugins =
plugin_name = module.path:PluginClass
+Standalone Plugin vs In-repo Plugin
+-----------------------------------
+
+Since all that's required for a plugin to be detected by tempest is a valid
+setuptools entry point in the proper namespace there is no difference from the
+tempest perspective on either creating a separate python package to
+house the plugin or adding the code to an existing python project. However,
+there are tradeoffs to consider when deciding which approach to take when
+creating a new plugin.
+
+If you create a separate python project for your plugin this makes a lot of
+things much easier. Firstly it makes packaging and versioning much simpler, you
+can easily decouple the requirements for the plugin from the requirements for
+the other project. It lets you version the plugin independently and maintain a
+single version of the test code across project release boundaries (see the
+`Branchless Tempest Spec`_ for more details on this). It also greatly
+simplifies the install time story for external users. Instead of having to
+install the right version of a project in the same python namespace as tempest
+they simply need to pip install the plugin in that namespace. It also means
+that users don't have to worry about inadvertently installing a tempest plugin
+when they install another package.
+
+.. _Branchless Tempest Spec: http://specs.openstack.org/openstack/qa-specs/specs/tempest/implemented/branchless-tempest.html
+
+The sole advantage to integrating a plugin into an existing python project is
+that it enables you to land code changes at the same time you land test changes
+in the plugin. This reduces some of the burden on contributors by not having
+to land 2 changes to add a new API feature and then test it and doing it as a
+single combined commit.
+
+
Plugin Class
============
diff --git a/etc/accounts.yaml.sample b/etc/accounts.yaml.sample
index decc659..3dbed79 100644
--- a/etc/accounts.yaml.sample
+++ b/etc/accounts.yaml.sample
@@ -3,7 +3,25 @@
# This is required to provide isolation between test for running in parallel
#
# Valid fields for credentials are defined in the descendants of
-# auth.Credentials - see KeystoneV[2|3]Credentials.CONF_ATTRIBUTES
+# lib.auth.Credentials - see KeystoneV[2|3]Credentials.ATTRIBUTES
+#
+# The fields in KeystoneV3Credentials behave as follows:
+#
+# tenant_[id|name] also sets project_[id|name].
+#
+# project_[id|name] also sets tenant_[id|name].
+#
+# Providing distinct values for both tenant_[id|name] and project_[id|name]
+# will result in an InvalidCredentials exception.
+#
+# The value of project_domain_[id|name] is used for user_domain_[id|name] if
+# the latter is not specified.
+#
+# The value of user_domain_[id|name] is used for project_domain_[id|name] if
+# the latter is not specified.
+#
+# The value of domain_[id|name] is used for project_domain_[id|name] if not
+# specified and user_domain_[id|name] if not specified.
- username: 'user_1'
tenant_name: 'test_tenant_1'
diff --git a/releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml b/releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml
new file mode 100644
index 0000000..217c2f6
--- /dev/null
+++ b/releasenotes/notes/10.0-supported-openstack-releases-b88db468695348f6.yaml
@@ -0,0 +1,13 @@
+---
+other:
+ - OpenStack Releases Supported at this time are the same as in the
+ previous release 9,
+ **Kilo** and
+ **Liberty**.
+
+
+ The release under current development as of this tag is Mitaka,
+ meaning that every Tempest commit is also tested against master during
+ the Mitaka cycle. However, this does not necessarily mean that using
+ Tempest as of this tag will work against a Mitaka (or future releases)
+ cloud.
diff --git a/releasenotes/notes/Tempest-library-interface-0eb680b810139a50.yaml b/releasenotes/notes/Tempest-library-interface-0eb680b810139a50.yaml
new file mode 100644
index 0000000..0ed3130
--- /dev/null
+++ b/releasenotes/notes/Tempest-library-interface-0eb680b810139a50.yaml
@@ -0,0 +1,11 @@
+---
+prelude: |
+ This release includes the addition of the stable library interface for
+ tempest. This behaves just as tempest-lib did prior to this, but instead
+ it lives directly in the tempest project. For more information refer to
+ the `library docs`_.
+
+ .. _library docs: http://docs.openstack.org/developer/tempest/library.html#library
+
+features:
+ - Tempest library interface
diff --git a/releasenotes/notes/api-microversion-testing-support-2ceddd2255670932.yaml b/releasenotes/notes/api-microversion-testing-support-2ceddd2255670932.yaml
new file mode 100644
index 0000000..e98671a
--- /dev/null
+++ b/releasenotes/notes/api-microversion-testing-support-2ceddd2255670932.yaml
@@ -0,0 +1,3 @@
+---
+features:
+ - Tempest library interface addition(API Microversion testing interfaces).
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 46ebbc5..9dd57a9 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=1.6 # Apache-2.0
-cliff!=1.16.0,>=1.15.0 # Apache-2.0
+cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0
anyjson>=0.3.3 # BSD
httplib2>=0.7.5 # MIT
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
@@ -11,12 +11,12 @@
netaddr!=0.7.16,>=0.7.12 # BSD
testrepository>=0.0.18 # Apache-2.0/BSD
pyOpenSSL>=0.14 # Apache-2.0
-oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=3.4.0 # Apache-2.0
+oslo.concurrency>=3.5.0 # Apache-2.0
+oslo.config>=3.7.0 # Apache-2.0
oslo.i18n>=2.1.0 # Apache-2.0
oslo.log>=1.14.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
-oslo.utils>=3.4.0 # Apache-2.0
+oslo.utils>=3.5.0 # Apache-2.0
six>=1.9.0 # MIT
iso8601>=0.1.9 # MIT
fixtures>=1.3.1 # Apache-2.0/BSD
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index b1c42a6..ead6db3 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -63,7 +63,7 @@
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, volume_backed):
+ def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
block_migration = (CONF.compute_feature_enabled.
block_migration_for_live_migration and
not volume_backed)
diff --git a/tempest/api/compute/api_microversion_fixture.py b/tempest/api/compute/api_microversion_fixture.py
index bf4de3e..695af52 100644
--- a/tempest/api/compute/api_microversion_fixture.py
+++ b/tempest/api/compute/api_microversion_fixture.py
@@ -14,7 +14,7 @@
import fixtures
-from tempest.services.compute.json import base_compute_client
+from tempest.lib.services.compute import base_compute_client
class APIMicroversionFixture(fixtures.Fixture):
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ee21284..77ed7cd 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -18,12 +18,12 @@
from oslo_log import log as logging
from tempest.api.compute import api_microversion_fixture
-from tempest.common import api_version_utils
from tempest.common import compute
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
from tempest import exceptions
+from tempest.lib.common import api_version_utils
from tempest.lib import exceptions as lib_exc
import tempest.test
@@ -47,8 +47,8 @@
super(BaseV2ComputeTest, cls).skip_checks()
if not CONF.service_available.nova:
raise cls.skipException("Nova is not available")
- cfg_min_version = CONF.compute_feature_enabled.min_microversion
- cfg_max_version = CONF.compute_feature_enabled.max_microversion
+ cfg_min_version = CONF.compute.min_microversion
+ cfg_max_version = CONF.compute.max_microversion
api_version_utils.check_skip_with_microversion(cls.min_microversion,
cls.max_microversion,
cfg_min_version,
@@ -105,7 +105,7 @@
cls.request_microversion = (
api_version_utils.select_request_microversion(
cls.min_microversion,
- CONF.compute_feature_enabled.min_microversion))
+ CONF.compute.min_microversion))
cls.build_interval = CONF.compute.build_interval
cls.build_timeout = CONF.compute.build_timeout
cls.image_ref = CONF.compute.image_ref
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 63ba650..e91944f 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -67,7 +67,7 @@
resp = {}
resp['status'] = None
self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
- '!@$%^&*()', name=name, meta=meta)
+ '!@$^&*()', name=name, meta=meta)
@test.attr(type=['negative'])
@test.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 0b33d66..c1fbb12 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -14,7 +14,6 @@
# under the License.
from tempest.api.compute import base
-from tempest.api import utils
from tempest.common import fixed_network
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -89,7 +88,7 @@
wait_until='ACTIVE')
@test.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
- @utils.skip_unless_attr('multiple_images', 'Only one image found')
+ @decorators.skip_unless_attr('multiple_images', 'Only one image found')
def test_list_servers_filter_by_image(self):
# Filter the list of servers by image
params = {'image': self.image_ref}
@@ -174,7 +173,7 @@
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')
+ @decorators.skip_unless_attr('multiple_images', 'Only one image found')
def test_list_servers_detailed_filter_by_image(self):
# Filter the detailed list of servers by image
params = {'image': self.image_ref}
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 ff53187..18a50d0 100644
--- a/tempest/api/identity/admin/v3/test_default_project_id.py
+++ b/tempest/api/identity/admin/v3/test_default_project_id.py
@@ -71,8 +71,8 @@
admin_role_id = admin_role['id']
# grant the admin role to the user on his project
- self.client.assign_user_role_on_project(proj_id, user_id,
- admin_role_id)
+ self.roles_client.assign_user_role_on_project(proj_id, user_id,
+ admin_role_id)
# create a new client with user's credentials (NOTE: unscoped token!)
creds = auth.KeystoneV3Credentials(username=user_name,
diff --git a/tempest/api/identity/admin/v3/test_inherits.py b/tempest/api/identity/admin/v3/test_inherits.py
new file mode 100644
index 0000000..fe20349
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_inherits.py
@@ -0,0 +1,147 @@
+# 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.identity import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class BaseInheritsV3Test(base.BaseIdentityV3AdminTest):
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseInheritsV3Test, cls).skip_checks()
+ if not test.is_extension_enabled('OS-INHERIT', 'identity'):
+ raise cls.skipException("Inherits aren't enabled")
+
+ @classmethod
+ def resource_setup(cls):
+ super(BaseInheritsV3Test, cls).resource_setup()
+ u_name = data_utils.rand_name('user-')
+ u_desc = '%s description' % u_name
+ u_email = '%s@testmail.tm' % u_name
+ u_password = data_utils.rand_name('pass-')
+ cls.domain = cls.domains_client.create_domain(
+ data_utils.rand_name('domain-'),
+ description=data_utils.rand_name('domain-desc-'))['domain']
+ cls.project = cls.projects_client.create_project(
+ data_utils.rand_name('project-'),
+ description=data_utils.rand_name('project-desc-'),
+ domain_id=cls.domain['id'])['project']
+ cls.group = cls.groups_client.create_group(
+ name=data_utils.rand_name('group-'), project_id=cls.project['id'],
+ domain_id=cls.domain['id'])['group']
+ cls.user = cls.users_client.create_user(
+ u_name, description=u_desc, password=u_password,
+ email=u_email, project_id=cls.project['id'],
+ domain_id=cls.domain['id'])['user']
+
+ @classmethod
+ def resource_cleanup(cls):
+ cls.groups_client.delete_group(cls.group['id'])
+ cls.users_client.delete_user(cls.user['id'])
+ cls.projects_client.delete_project(cls.project['id'])
+ cls.domains_client.update_domain(cls.domain['id'], enabled=False)
+ cls.domains_client.delete_domain(cls.domain['id'])
+ super(BaseInheritsV3Test, cls).resource_cleanup()
+
+ def _list_assertions(self, body, fetched_role_ids, role_id):
+ self.assertEqual(len(body), 1)
+ self.assertIn(role_id, fetched_role_ids)
+
+
+class InheritsV3TestJSON(BaseInheritsV3Test):
+
+ @test.idempotent_id('4e6f0366-97c8-423c-b2be-41eae6ac91c8')
+ def test_inherit_assign_list_check_revoke_roles_on_domains_user(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ # Assign role on domains user
+ self.roles_client.assign_inherited_role_on_domains_user(
+ self.domain['id'], self.user['id'], src_role['id'])
+ # list role on domains user
+ roles = self.roles_client.\
+ list_inherited_project_role_for_user_on_domain(
+ self.domain['id'], self.user['id'])['roles']
+
+ fetched_role_ids = [i['id'] for i in roles]
+ self._list_assertions(roles, fetched_role_ids,
+ src_role['id'])
+
+ # Check role on domains user
+ self.roles_client.check_user_inherited_project_role_on_domain(
+ self.domain['id'], self.user['id'], src_role['id'])
+ # Revoke role from domains user.
+ self.roles_client.revoke_inherited_role_from_user_on_domain(
+ self.domain['id'], self.user['id'], src_role['id'])
+
+ @test.idempotent_id('c7a8dda2-be50-4fb4-9a9c-e830771078b1')
+ def test_inherit_assign_list_check_revoke_roles_on_domains_group(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ # Assign role on domains group
+ self.roles_client.assign_inherited_role_on_domains_group(
+ self.domain['id'], self.group['id'], src_role['id'])
+ # List role on domains group
+ roles = self.roles_client.\
+ list_inherited_project_role_for_group_on_domain(
+ self.domain['id'], self.group['id'])['roles']
+
+ fetched_role_ids = [i['id'] for i in roles]
+ self._list_assertions(roles, fetched_role_ids,
+ src_role['id'])
+
+ # Check role on domains group
+ self.roles_client.check_group_inherited_project_role_on_domain(
+ self.domain['id'], self.group['id'], src_role['id'])
+ # Revoke role from domains group
+ self.roles_client.revoke_inherited_role_from_group_on_domain(
+ self.domain['id'], self.group['id'], src_role['id'])
+
+ @test.idempotent_id('18b70e45-7687-4b72-8277-b8f1a47d7591')
+ def test_inherit_assign_check_revoke_roles_on_projects_user(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ # Assign role on projects user
+ self.roles_client.assign_inherited_role_on_projects_user(
+ self.project['id'], self.user['id'], src_role['id'])
+ # Check role on projects user
+ self.roles_client.check_user_has_flag_on_inherited_to_project(
+ self.project['id'], self.user['id'], src_role['id'])
+ # Revoke role from projects user
+ self.roles_client.revoke_inherited_role_from_user_on_project(
+ self.project['id'], self.user['id'], src_role['id'])
+
+ @test.idempotent_id('26021436-d5a4-4256-943c-ded01e0d4b45')
+ def test_inherit_assign_check_revoke_roles_on_projects_group(self):
+ # Create role
+ src_role = self.roles_client.create_role(
+ name=data_utils.rand_name('Role'))['role']
+ self.addCleanup(self.roles_client.delete_role, src_role['id'])
+ # Assign role on projects group
+ self.roles_client.assign_inherited_role_on_projects_group(
+ self.project['id'], self.group['id'], src_role['id'])
+ # Check role on projects group
+ self.roles_client.check_group_has_flag_on_inherited_to_project(
+ self.project['id'], self.group['id'], src_role['id'])
+ # Revoke role from projects group
+ self.roles_client.revoke_inherited_role_from_group_on_project(
+ self.project['id'], self.group['id'], src_role['id'])
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index a0a842c..12ef369 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -25,7 +25,7 @@
super(RolesV3TestJSON, cls).resource_setup()
for _ in range(3):
role_name = data_utils.rand_name(name='role')
- role = cls.client.create_role(name=role_name)['role']
+ role = cls.roles_client.create_role(name=role_name)['role']
cls.data.roles.append(role)
cls.fetched_role_ids = list()
u_name = data_utils.rand_name('user')
@@ -46,12 +46,12 @@
u_name, description=u_desc, password=cls.u_password,
email=u_email, project_id=cls.project['id'],
domain_id=cls.domain['id'])['user']
- cls.role = cls.client.create_role(
+ cls.role = cls.roles_client.create_role(
name=data_utils.rand_name('Role'))['role']
@classmethod
def resource_cleanup(cls):
- cls.client.delete_role(cls.role['id'])
+ cls.roles_client.delete_role(cls.role['id'])
cls.groups_client.delete_group(cls.group_body['id'])
cls.users_client.delete_user(cls.user_body['id'])
cls.projects_client.delete_project(cls.project['id'])
@@ -67,34 +67,35 @@
@test.attr(type='smoke')
@test.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
- def test_role_create_update_get_list(self):
+ def test_role_create_update_show_list(self):
r_name = data_utils.rand_name('Role')
- role = self.client.create_role(name=r_name)['role']
- self.addCleanup(self.client.delete_role, role['id'])
+ role = self.roles_client.create_role(name=r_name)['role']
+ self.addCleanup(self.roles_client.delete_role, role['id'])
self.assertIn('name', role)
self.assertEqual(role['name'], r_name)
new_name = data_utils.rand_name('NewRole')
- updated_role = self.client.update_role(role['id'],
- name=new_name)['role']
+ updated_role = self.roles_client.update_role(role['id'],
+ name=new_name)['role']
self.assertIn('name', updated_role)
self.assertIn('id', updated_role)
self.assertIn('links', updated_role)
self.assertNotEqual(r_name, updated_role['name'])
- new_role = self.client.show_role(role['id'])['role']
+ new_role = self.roles_client.show_role(role['id'])['role']
self.assertEqual(new_name, new_role['name'])
self.assertEqual(updated_role['id'], new_role['id'])
- roles = self.client.list_roles()['roles']
+ roles = self.roles_client.list_roles()['roles']
self.assertIn(role['id'], [r['id'] for r in roles])
@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'])
+ self.roles_client.assign_user_role_on_project(self.project['id'],
+ self.user_body['id'],
+ self.role['id'])
- roles = self.client.list_user_roles_on_project(
+ roles = self.roles_client.list_user_roles_on_project(
self.project['id'], self.user_body['id'])['roles']
for i in roles:
@@ -103,18 +104,18 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.check_user_role_existence_on_project(
+ self.roles_client.check_user_role_existence_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
- self.client.delete_role_from_user_on_project(
+ self.roles_client.delete_role_from_user_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
@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.roles_client.assign_user_role_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
- roles = self.client.list_user_roles_on_domain(
+ roles = self.roles_client.list_user_roles_on_domain(
self.domain['id'], self.user_body['id'])['roles']
for i in roles:
@@ -123,19 +124,19 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.check_user_role_existence_on_domain(
+ self.roles_client.check_user_role_existence_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
- self.client.delete_role_from_user_on_domain(
+ self.roles_client.delete_role_from_user_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
@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(
+ self.roles_client.assign_group_role_on_project(
self.project['id'], self.group_body['id'], self.role['id'])
# List group roles on project
- roles = self.client.list_group_roles_on_project(
+ roles = self.roles_client.list_group_roles_on_project(
self.project['id'], self.group_body['id'])['roles']
for i in roles:
@@ -157,19 +158,19 @@
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])
- self.client.check_role_from_group_on_project_existence(
+ self.roles_client.check_role_from_group_on_project_existence(
self.project['id'], self.group_body['id'], self.role['id'])
# Revoke role to group on project
- self.client.delete_role_from_group_on_project(
+ self.roles_client.delete_role_from_group_on_project(
self.project['id'], self.group_body['id'], self.role['id'])
@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.roles_client.assign_group_role_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
- roles = self.client.list_group_roles_on_domain(
+ roles = self.roles_client.list_group_roles_on_domain(
self.domain['id'], self.group_body['id'])['roles']
for i in roles:
@@ -178,15 +179,15 @@
self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- self.client.check_role_from_group_on_domain_existence(
+ self.roles_client.check_role_from_group_on_domain_existence(
self.domain['id'], self.group_body['id'], self.role['id'])
- self.client.delete_role_from_group_on_domain(
+ self.roles_client.delete_role_from_group_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
@test.idempotent_id('f5654bcc-08c4-4f71-88fe-05d64e06de94')
def test_list_roles(self):
# Return a list of all roles
- body = self.client.list_roles()['roles']
+ body = self.roles_client.list_roles()['roles']
found = [role for role in body if role in self.data.roles]
self.assertEqual(len(found), len(self.data.roles))
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 63ba158..6f12939 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -77,15 +77,17 @@
# Create a role
role_name = data_utils.rand_name(name='role')
- role = self.client.create_role(name=role_name)['role']
- self.addCleanup(self.client.delete_role, role['id'])
+ role = self.roles_client.create_role(name=role_name)['role']
+ self.addCleanup(self.roles_client.delete_role, role['id'])
# Grant the user the role on both projects.
- self.client.assign_user_role_on_project(project1['id'], user['id'],
- role['id'])
+ self.roles_client.assign_user_role_on_project(project1['id'],
+ user['id'],
+ role['id'])
- self.client.assign_user_role_on_project(project2['id'], user['id'],
- role['id'])
+ self.roles_client.assign_user_role_on_project(project2['id'],
+ user['id'],
+ role['id'])
# Get an unscoped token.
token_auth = self.token.auth(user_id=user['id'],
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index d31514c..09ae468 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -69,19 +69,22 @@
self.delegated_role = data_utils.rand_name('DelegatedRole')
self.not_delegated_role = data_utils.rand_name('NotDelegatedRole')
- role = self.client.create_role(name=self.delegated_role)['role']
+ role = self.roles_client.create_role(name=self.delegated_role)['role']
self.delegated_role_id = role['id']
- role = self.client.create_role(name=self.not_delegated_role)['role']
+ role = self.roles_client.create_role(
+ name=self.not_delegated_role)['role']
self.not_delegated_role_id = role['id']
# Assign roles to trustor
- self.client.assign_user_role_on_project(self.trustor_project_id,
- self.trustor_user_id,
- self.delegated_role_id)
- self.client.assign_user_role_on_project(self.trustor_project_id,
- self.trustor_user_id,
- self.not_delegated_role_id)
+ self.roles_client.assign_user_role_on_project(
+ self.trustor_project_id,
+ self.trustor_user_id,
+ self.delegated_role_id)
+ self.roles_client.assign_user_role_on_project(
+ self.trustor_project_id,
+ self.trustor_user_id,
+ self.not_delegated_role_id)
# Get trustee user ID, use the demo user
trustee_username = self.non_admin_client.user
@@ -105,9 +108,9 @@
if self.trustor_project_id:
self.projects_client.delete_project(self.trustor_project_id)
if self.delegated_role_id:
- self.client.delete_role(self.delegated_role_id)
+ self.roles_client.delete_role(self.delegated_role_id)
if self.not_delegated_role_id:
- self.client.delete_role(self.not_delegated_role_id)
+ self.roles_client.delete_role(self.not_delegated_role_id)
def create_trust(self, impersonate=True, expires=None):
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index de659d8..e26624a 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -117,13 +117,13 @@
# Delete the User at the end of this method
self.addCleanup(self.users_client.delete_user, user_body['id'])
# Creating Role
- role_body = self.client.create_role(
+ role_body = self.roles_client.create_role(
name=data_utils.rand_name('role'))['role']
# Delete the Role at the end of this method
- self.addCleanup(self.client.delete_role, role_body['id'])
+ self.addCleanup(self.roles_client.delete_role, role_body['id'])
user = self.users_client.show_user(user_body['id'])['user']
- role = self.client.show_role(role_body['id'])['role']
+ role = self.roles_client.show_role(role_body['id'])['role']
for i in range(2):
# Creating project so as to assign role
project_body = self.projects_client.create_project(
@@ -135,9 +135,9 @@
self.addCleanup(
self.projects_client.delete_project, project_body['id'])
# Assigning roles to user on project
- self.client.assign_user_role_on_project(project['id'],
- user['id'],
- role['id'])
+ self.roles_client.assign_user_role_on_project(project['id'],
+ user['id'],
+ role['id'])
assigned_project_ids.append(project['id'])
body = self.users_client.list_user_projects(user['id'])['projects']
for i in body:
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 849b761..3bcae17 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -106,14 +106,14 @@
cls.non_admin_roles_client = cls.os.roles_client
cls.users_client = cls.os_adm.users_client
cls.non_admin_users_client = cls.os.users_client
- cls.services_client = cls.os_adm.services_v2_client
- cls.endpoints_client = cls.os_adm.endpoints_v2_client
+ cls.services_client = cls.os_adm.identity_services_client
+ cls.endpoints_client = cls.os_adm.endpoints_client
@classmethod
def resource_setup(cls):
super(BaseIdentityV2AdminTest, cls).resource_setup()
- cls.data = DataGeneratorV2(cls.client, cls.tenants_client,
- cls.users_client, cls.roles_client)
+ cls.data = DataGeneratorV2(cls.tenants_client, cls.users_client,
+ cls.roles_client)
@classmethod
def resource_cleanup(cls):
@@ -153,10 +153,11 @@
cls.domains_client = cls.os_adm.domains_client
cls.users_client = cls.os_adm.users_v3_client
cls.trusts_client = cls.os_adm.trusts_client
+ cls.roles_client = cls.os_adm.roles_v3_client
cls.token = cls.os_adm.token_v3_client
- cls.endpoints_client = cls.os_adm.endpoints_client
+ cls.endpoints_client = cls.os_adm.endpoints_v3_client
cls.regions_client = cls.os_adm.regions_client
- cls.services_client = cls.os_adm.identity_services_client
+ cls.services_client = cls.os_adm.identity_services_v3_client
cls.policies_client = cls.os_adm.policies_client
cls.creds_client = cls.os_adm.credentials_client
cls.groups_client = cls.os_adm.groups_client
@@ -165,8 +166,8 @@
@classmethod
def resource_setup(cls):
super(BaseIdentityV3AdminTest, cls).resource_setup()
- cls.data = DataGeneratorV3(cls.client, cls.projects_client,
- cls.users_client, None, cls.domains_client)
+ cls.data = DataGeneratorV3(cls.projects_client, cls.users_client,
+ cls.roles_client, cls.domains_client)
@classmethod
def resource_cleanup(cls):
@@ -174,13 +175,6 @@
super(BaseIdentityV3AdminTest, cls).resource_cleanup()
@classmethod
- def get_role_by_name(cls, name):
- roles = cls.client.list_roles()['roles']
- role = [r for r in roles if r['name'] == name]
- if len(role) > 0:
- return role[0]
-
- @classmethod
def disable_user(cls, user_name, domain_id=None):
user = cls.get_user_by_name(user_name, domain_id)
cls.users_client.update_user(user['id'], user_name, enabled=False)
@@ -194,12 +188,11 @@
class BaseDataGenerator(object):
- def __init__(self, client, projects_client,
- users_client, roles_client=None, domains_client=None):
- self.client = client
+ def __init__(self, projects_client, users_client, roles_client,
+ domains_client=None):
self.projects_client = projects_client
self.users_client = users_client
- self.roles_client = roles_client or client
+ self.roles_client = roles_client
self.domains_client = domains_client
self.user_password = None
diff --git a/tempest/api/identity/v3/test_projects.py b/tempest/api/identity/v3/test_projects.py
index 7049bcf..995b77e 100644
--- a/tempest/api/identity/v3/test_projects.py
+++ b/tempest/api/identity/v3/test_projects.py
@@ -33,10 +33,14 @@
# user can successfully authenticate using his credentials and
# project name from received projects list
for project in resp['projects']:
+ # 'user_domain_id' needs to be specified otherwise tempest_lib
+ # assumes it to be 'default'
token_id, body = self.non_admin_token.get_token(
username=self.os.credentials.username,
+ user_domain_id=self.os.credentials.user_domain_id,
password=self.os.credentials.password,
project_name=project['name'],
+ project_domain_id=project['domain_id'],
auth_data=True)
self.assertNotEmpty(token_id)
self.assertEqual(body['project']['id'], project['id'])
@@ -48,5 +52,7 @@
lib_exc.Unauthorized,
self.non_admin_token.get_token,
username=self.os.credentials.username,
+ user_domain_id=self.os.credentials.user_domain_id,
password=self.os.credentials.password,
- project_name=alt_project_name)
+ project_name=alt_project_name,
+ project_domain_id=project['domain_id'])
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index 3151763..593bf2a 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -28,10 +28,15 @@
user_id = creds.user_id
username = creds.username
password = creds.password
+ user_domain_id = creds.user_domain_id
- token_id, resp = self.non_admin_token.get_token(user_id=user_id,
- password=password,
- auth_data=True)
+ # 'user_domain_id' needs to be specified otherwise tempest_lib assumes
+ # it to be 'default'
+ token_id, resp = self.non_admin_token.get_token(
+ user_id=user_id,
+ user_domain_id=user_domain_id,
+ password=password,
+ auth_data=True)
self.assertNotEmpty(token_id)
self.assertIsInstance(token_id, six.string_types)
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index 78d6aea..7a4547a 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -74,14 +74,14 @@
# query and setup steps are only required if the extension is available
# and only if the router's default type is distributed.
if test.is_extension_enabled('dvr', 'network'):
- cls.is_dvr_router = cls.admin_client.show_router(
+ cls.is_dvr_router = cls.admin_routers_client.show_router(
cls.router['id'])['router'].get('distributed', False)
if cls.is_dvr_router:
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
cls.port = cls.create_port(cls.network)
- cls.client.add_router_interface(cls.router['id'],
- port_id=cls.port['id'])
+ cls.routers_client.add_router_interface(
+ cls.router['id'], port_id=cls.port['id'])
# NOTE: Sometimes we have seen this test fail with dvr in,
# multinode tests, since the dhcp port is not created before
# the test gets executed and so the router is not scheduled
@@ -92,15 +92,15 @@
external_gateway_info = {
'network_id': CONF.network.public_network_id,
'enable_snat': True}
- cls.admin_client.update_router_with_snat_gw_info(
+ cls.admin_routers_client.update_router_with_snat_gw_info(
cls.router['id'],
external_gateway_info=external_gateway_info)
@classmethod
def resource_cleanup(cls):
if cls.is_dvr_router:
- cls.client.remove_router_interface(cls.router['id'],
- port_id=cls.port['id'])
+ cls.routers_client.remove_router_interface(cls.router['id'],
+ port_id=cls.port['id'])
super(L3AgentSchedulerTestJSON, cls).resource_cleanup()
@test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
@@ -114,7 +114,8 @@
self.agent['id'],
router_id=self.router['id'])
body = (
- self.admin_client.list_l3_agents_hosting_router(self.router['id']))
+ self.admin_routers_client.list_l3_agents_hosting_router(
+ self.router['id']))
for agent in body['agents']:
l3_agent_ids.append(agent['id'])
self.assertIn('agent_type', agent)
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index a1a881d..c1cdbf2 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -60,7 +60,7 @@
n2['network']['id'])
# Try to create a third network while the quota is two
- with self.assertRaisesRegexp(
+ with self.assertRaisesRegex(
lib_exc.Conflict,
"An object with that identifier already exists\\n" +
"Details.*Quota exceeded for resources: \['network'\].*"):
diff --git a/tempest/api/network/admin/test_routers_dvr.py b/tempest/api/network/admin/test_routers_dvr.py
index 3e787af..2bc86ad 100644
--- a/tempest/api/network/admin/test_routers_dvr.py
+++ b/tempest/api/network/admin/test_routers_dvr.py
@@ -34,8 +34,8 @@
# has a distributed attribute.
super(RoutersTestDVR, cls).resource_setup()
name = data_utils.rand_name('pretest-check')
- router = cls.admin_client.create_router(name)
- cls.admin_client.delete_router(router['router']['id'])
+ router = cls.admin_routers_client.create_router(name)
+ cls.admin_routers_client.delete_router(router['router']['id'])
if 'distributed' not in router['router']:
msg = "'distributed' flag not found. DVR Possibly not enabled"
raise cls.skipException(msg)
@@ -53,8 +53,9 @@
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 = self.admin_routers_client.create_router(name,
+ distributed=True)
+ self.addCleanup(self.admin_routers_client.delete_router,
router['router']['id'])
self.assertTrue(router['router']['distributed'])
@@ -72,8 +73,9 @@
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 = self.admin_routers_client.create_router(name,
+ distributed=False)
+ self.addCleanup(self.admin_routers_client.delete_router,
router['router']['id'])
self.assertFalse(router['router']['distributed'])
@@ -93,11 +95,12 @@
"""
name = data_utils.rand_name('router')
# router needs to be in admin state down in order to be upgraded to DVR
- router = self.admin_client.create_router(name, distributed=False,
- admin_state_up=False)
- self.addCleanup(self.admin_client.delete_router,
+ router = self.admin_routers_client.create_router(name,
+ distributed=False,
+ admin_state_up=False)
+ self.addCleanup(self.admin_routers_client.delete_router,
router['router']['id'])
self.assertFalse(router['router']['distributed'])
- router = self.admin_client.update_router(router['router']['id'],
- distributed=True)
+ router = self.admin_routers_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 1e636f1..8e0c361 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -71,6 +71,7 @@
cls.agents_client = cls.os.network_agents_client
cls.network_extensions_client = cls.os.network_extensions_client
cls.networks_client = cls.os.networks_client
+ cls.routers_client = cls.os.routers_client
cls.subnetpools_client = cls.os.subnetpools_client
cls.subnets_client = cls.os.subnets_client
cls.ports_client = cls.os.ports_client
@@ -231,7 +232,7 @@
ext_gw_info['network_id'] = external_network_id
if enable_snat is not None:
ext_gw_info['enable_snat'] = enable_snat
- body = cls.client.create_router(
+ body = cls.routers_client.create_router(
router_name, external_gateway_info=ext_gw_info,
admin_state_up=admin_state_up, **kwargs)
router = body['router']
@@ -250,8 +251,8 @@
@classmethod
def create_router_interface(cls, router_id, subnet_id):
"""Wrapper utility that returns a router interface."""
- interface = cls.client.add_router_interface(router_id,
- subnet_id=subnet_id)
+ interface = cls.routers_client.add_router_interface(
+ router_id, subnet_id=subnet_id)
return interface
@classmethod
@@ -260,12 +261,12 @@
interfaces = body['ports']
for i in interfaces:
try:
- cls.client.remove_router_interface(
+ cls.routers_client.remove_router_interface(
router['id'],
subnet_id=i['fixed_ips'][0]['subnet_id'])
except lib_exc.NotFound:
pass
- cls.client.delete_router(router['id'])
+ cls.routers_client.delete_router(router['id'])
class BaseAdminNetworkTest(BaseNetworkTest):
@@ -278,6 +279,7 @@
cls.admin_client = cls.os_adm.network_client
cls.admin_agents_client = cls.os_adm.network_agents_client
cls.admin_networks_client = cls.os_adm.networks_client
+ cls.admin_routers_client = cls.os_adm.routers_client
cls.admin_subnets_client = cls.os_adm.subnets_client
cls.admin_ports_client = cls.os_adm.ports_client
cls.admin_quotas_client = cls.os_adm.network_quotas_client
diff --git a/tempest/api/network/base_routers.py b/tempest/api/network/base_routers.py
index 3495b76f..807257f 100644
--- a/tempest/api/network/base_routers.py
+++ b/tempest/api/network/base_routers.py
@@ -33,31 +33,31 @@
self.addCleanup(self._cleanup_router, router)
return router
- def _delete_router(self, router_id, network_client=None):
- client = network_client or self.client
+ def _delete_router(self, router_id, routers_client=None):
+ client = routers_client or self.routers_client
client.delete_router(router_id)
# Asserting that the router is not found in the list
# after deletion
- list_body = self.client.list_routers()
+ list_body = self.routers_client.list_routers()
routers_list = list()
for router in list_body['routers']:
routers_list.append(router['id'])
self.assertNotIn(router_id, routers_list)
def _add_router_interface_with_subnet_id(self, router_id, subnet_id):
- interface = self.client.add_router_interface(router_id,
- subnet_id=subnet_id)
+ interface = self.routers_client.add_router_interface(
+ router_id, subnet_id=subnet_id)
self.addCleanup(self._remove_router_interface_with_subnet_id,
router_id, subnet_id)
self.assertEqual(subnet_id, interface['subnet_id'])
return interface
def _remove_router_interface_with_subnet_id(self, router_id, subnet_id):
- body = self.client.remove_router_interface(router_id,
- subnet_id=subnet_id)
+ body = self.routers_client.remove_router_interface(router_id,
+ subnet_id=subnet_id)
self.assertEqual(subnet_id, body['subnet_id'])
def _remove_router_interface_with_port_id(self, router_id, port_id):
- body = self.client.remove_router_interface(router_id,
- port_id=port_id)
+ body = self.routers_client.remove_router_interface(router_id,
+ port_id=port_id)
self.assertEqual(port_id, body['port_id'])
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index f59ecff..77008ab 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -68,8 +68,8 @@
for port in ports:
if (port['device_owner'].startswith('network:router_interface') and
port['device_id'] in [r['id'] for r in self.routers]):
- self.client.remove_router_interface(port['device_id'],
- port_id=port['id'])
+ self.routers_client.remove_router_interface(port['device_id'],
+ port_id=port['id'])
else:
if port['id'] in [p['id'] for p in self.ports]:
self.ports_client.delete_port(port['id'])
@@ -80,11 +80,11 @@
if subnet['id'] in [s['id'] for s in self.subnets]:
self.subnets_client.delete_subnet(subnet['id'])
self._remove_from_list_by_index(self.subnets, subnet)
- body = self.client.list_routers()
+ body = self.routers_client.list_routers()
routers = body['routers']
for router in routers:
if router['id'] in [r['id'] for r in self.routers]:
- self.client.delete_router(router['id'])
+ self.routers_client.delete_router(router['id'])
self._remove_from_list_by_index(self.routers, router)
def _get_ips_from_subnet(self, **kwargs):
@@ -338,12 +338,12 @@
fixed_ips=[
{'subnet_id': subnet['id'],
'ip_address': ip}])
- self.assertRaisesRegexp(lib_exc.Conflict,
- "object with that identifier already exists",
- self.create_port,
- self.network,
- fixed_ips=[{'subnet_id': subnet['id'],
- 'ip_address': ip}])
+ self.assertRaisesRegex(lib_exc.Conflict,
+ "object with that identifier already exists",
+ self.create_port,
+ self.network,
+ fixed_ips=[{'subnet_id': subnet['id'],
+ 'ip_address': ip}])
def _create_subnet_router(self, kwargs):
subnet = self.create_subnet(self.network, **kwargs)
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index ffe0336..fa1ed6a 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -12,10 +12,9 @@
# 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 itertools
-
import netaddr
import six
+import testtools
from tempest.api.network import base
from tempest.common import custom_matchers
@@ -376,6 +375,9 @@
@test.attr(type='smoke')
@test.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
+ @test.requires_ext(extension='external-net', service='network')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
def test_external_network_visibility(self):
"""Verifies user can see external networks but not subnets."""
body = self.networks_client.list_networks(**{'router:external': True})
@@ -387,17 +389,12 @@
self.assertEmpty(nonexternal, "Found non-external networks"
" in filtered list (%s)." % nonexternal)
self.assertIn(CONF.network.public_network_id, networks)
-
- subnets_iter = (network['subnets']
- for network in body['networks']
- if not network['shared'])
- # subnets_iter is a list (iterator) of lists. This flattens it to a
- # list of UUIDs
- public_subnets_iter = itertools.chain(*subnets_iter)
- body = self.subnets_client.list_subnets()
- subnets = [sub['id'] for sub in body['subnets']
- if sub['id'] in public_subnets_iter]
- self.assertEmpty(subnets, "Public subnets visible")
+ # only check the public network ID because the other networks may
+ # belong to other tests and their state may have changed during this
+ # test
+ body = self.subnets_client.list_subnets(
+ network_id=CONF.network.public_network_id)
+ self.assertEmpty(body['subnets'], "Public subnets visible")
class BulkNetworkOpsTestJSON(base.BaseNetworkTest):
@@ -451,7 +448,7 @@
# Creates 2 networks in one request
network_list = [{'name': data_utils.rand_name('network-')},
{'name': data_utils.rand_name('network-')}]
- body = self.client.create_bulk_network(networks=network_list)
+ body = self.networks_client.create_bulk_networks(networks=network_list)
created_networks = body['networks']
self.addCleanup(self._delete_networks, created_networks)
# Asserting that the networks are found in the list after creation
@@ -486,7 +483,7 @@
}
subnets_list.append(p1)
del subnets_list[1]['name']
- body = self.client.create_bulk_subnet(subnets=subnets_list)
+ body = self.subnets_client.create_bulk_subnets(subnets=subnets_list)
created_subnets = body['subnets']
self.addCleanup(self._delete_subnets, created_subnets)
# Asserting that the subnets are found in the list after creation
@@ -512,7 +509,7 @@
}
port_list.append(p1)
del port_list[1]['name']
- body = self.client.create_bulk_port(ports=port_list)
+ body = self.ports_client.create_bulk_ports(ports=port_list)
created_ports = body['ports']
self.addCleanup(self._delete_ports, created_ports)
# Asserting that the ports are found in the list after creation
@@ -621,7 +618,7 @@
subnet_ids = [subnet['id'] for subnet in subnets['subnets']]
self.assertNotIn(subnet_slaac['id'], subnet_ids,
"Subnet wasn't deleted")
- self.assertRaisesRegexp(
+ self.assertRaisesRegex(
lib_exc.Conflict,
"There are one or more ports still in use on the network",
self.networks_client.delete_network,
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index d7b220b..5ff23c6 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -75,7 +75,7 @@
network2 = self.create_network(network_name=name)
network_list = [network1['id'], network2['id']]
port_list = [{'network_id': net_id} for net_id in network_list]
- body = self.client.create_bulk_port(ports=port_list)
+ body = self.ports_client.create_bulk_ports(ports=port_list)
created_ports = body['ports']
port1 = created_ports[0]
port2 = created_ports[1]
@@ -197,13 +197,13 @@
subnet = self.create_subnet(network)
self.addCleanup(self.subnets_client.delete_subnet, subnet['id'])
router = self.create_router(data_utils.rand_name('router-'))
- self.addCleanup(self.client.delete_router, router['id'])
+ self.addCleanup(self.routers_client.delete_router, router['id'])
port = self.ports_client.create_port(network_id=network['id'])
# Add router interface to port created above
- self.client.add_router_interface(router['id'],
- port_id=port['port']['id'])
- self.addCleanup(self.client.remove_router_interface, router['id'],
- port_id=port['port']['id'])
+ self.routers_client.add_router_interface(router['id'],
+ port_id=port['port']['id'])
+ self.addCleanup(self.routers_client.remove_router_interface,
+ router['id'], port_id=port['port']['id'])
# List ports filtered by router_id
port_list = self.ports_client.list_ports(device_id=router['id'])
ports = port_list['ports']
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 0b64be4..01afc51 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -52,7 +52,7 @@
# NOTE(salv-orlando): Do not invoke self.create_router
# as we need to check the response code
name = data_utils.rand_name('router-')
- create_body = self.client.create_router(
+ create_body = self.routers_client.create_router(
name, external_gateway_info={
"network_id": CONF.network.public_network_id},
admin_state_up=False)
@@ -63,24 +63,25 @@
CONF.network.public_network_id)
self.assertEqual(create_body['router']['admin_state_up'], False)
# Show details of the created router
- show_body = self.client.show_router(create_body['router']['id'])
+ show_body = self.routers_client.show_router(
+ create_body['router']['id'])
self.assertEqual(show_body['router']['name'], name)
self.assertEqual(
show_body['router']['external_gateway_info']['network_id'],
CONF.network.public_network_id)
self.assertEqual(show_body['router']['admin_state_up'], False)
# List routers and verify if created router is there in response
- list_body = self.client.list_routers()
+ list_body = self.routers_client.list_routers()
routers_list = list()
for router in list_body['routers']:
routers_list.append(router['id'])
self.assertIn(create_body['router']['id'], routers_list)
# Update the name of router and verify if it is updated
updated_name = 'updated ' + name
- update_body = self.client.update_router(create_body['router']['id'],
- name=updated_name)
+ update_body = self.routers_client.update_router(
+ create_body['router']['id'], name=updated_name)
self.assertEqual(update_body['router']['name'], updated_name)
- show_body = self.client.show_router(
+ show_body = self.routers_client.show_router(
create_body['router']['id'])
self.assertEqual(show_body['router']['name'], updated_name)
@@ -95,9 +96,9 @@
self.addCleanup(self.identity_utils.delete_project, project_id)
name = data_utils.rand_name('router-')
- create_body = self.admin_client.create_router(name,
- tenant_id=project_id)
- self.addCleanup(self.admin_client.delete_router,
+ create_body = self.admin_routers_client.create_router(
+ name, tenant_id=project_id)
+ self.addCleanup(self.admin_routers_client.delete_router,
create_body['router']['id'])
self.assertEqual(project_id, create_body['router']['tenant_id'])
@@ -122,9 +123,9 @@
external_gateway_info = {
'network_id': CONF.network.public_network_id,
'enable_snat': enable_snat}
- create_body = self.admin_client.create_router(
+ create_body = self.admin_routers_client.create_router(
name, external_gateway_info=external_gateway_info)
- self.addCleanup(self.admin_client.delete_router,
+ self.addCleanup(self.admin_routers_client.delete_router,
create_body['router']['id'])
# Verify snat attributes after router creation
self._verify_router_gateway(create_body['router']['id'],
@@ -137,8 +138,8 @@
subnet = self.create_subnet(network)
router = self._create_router(data_utils.rand_name('router-'))
# Add router interface with subnet id
- interface = self.client.add_router_interface(router['id'],
- subnet_id=subnet['id'])
+ interface = self.routers_client.add_router_interface(
+ router['id'], subnet_id=subnet['id'])
self.addCleanup(self._remove_router_interface_with_subnet_id,
router['id'], subnet['id'])
self.assertIn('subnet_id', interface.keys())
@@ -158,7 +159,7 @@
port_body = self.ports_client.create_port(
network_id=network['id'])
# add router interface to port created above
- interface = self.client.add_router_interface(
+ interface = self.routers_client.add_router_interface(
router['id'],
port_id=port_body['port']['id'])
self.addCleanup(self._remove_router_interface_with_port_id,
@@ -172,7 +173,7 @@
router['id'])
def _verify_router_gateway(self, router_id, exp_ext_gw_info=None):
- show_body = self.admin_client.show_router(router_id)
+ show_body = self.admin_routers_client.show_router(router_id)
actual_ext_gw_info = show_body['router']['external_gateway_info']
if exp_ext_gw_info is None:
self.assertIsNone(actual_ext_gw_info)
@@ -198,7 +199,7 @@
@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(
+ self.routers_client.update_router(
router['id'],
external_gateway_info={
'network_id': CONF.network.public_network_id})
@@ -212,7 +213,7 @@
@test.requires_ext(extension='ext-gw-mode', service='network')
def test_update_router_set_gateway_with_snat_explicit(self):
router = self._create_router(data_utils.rand_name('router-'))
- self.admin_client.update_router_with_snat_gw_info(
+ self.admin_routers_client.update_router_with_snat_gw_info(
router['id'],
external_gateway_info={
'network_id': CONF.network.public_network_id,
@@ -227,7 +228,7 @@
@test.requires_ext(extension='ext-gw-mode', service='network')
def test_update_router_set_gateway_without_snat(self):
router = self._create_router(data_utils.rand_name('router-'))
- self.admin_client.update_router_with_snat_gw_info(
+ self.admin_routers_client.update_router_with_snat_gw_info(
router['id'],
external_gateway_info={
'network_id': CONF.network.public_network_id,
@@ -243,7 +244,8 @@
router = self._create_router(
data_utils.rand_name('router-'),
external_network_id=CONF.network.public_network_id)
- self.client.update_router(router['id'], external_gateway_info={})
+ self.routers_client.update_router(router['id'],
+ external_gateway_info={})
self._verify_router_gateway(router['id'])
# No gateway port expected
list_body = self.admin_ports_client.list_ports(
@@ -257,7 +259,7 @@
router = self._create_router(
data_utils.rand_name('router-'),
external_network_id=CONF.network.public_network_id)
- self.admin_client.update_router_with_snat_gw_info(
+ self.admin_routers_client.update_router_with_snat_gw_info(
router['id'],
external_gateway_info={
'network_id': CONF.network.public_network_id,
@@ -270,7 +272,7 @@
@test.idempotent_id('c86ac3a8-50bd-4b00-a6b8-62af84a0765c')
@test.requires_ext(extension='extraroute', service='network')
- def test_update_extra_route(self):
+ def test_update_delete_extra_route(self):
# Create different cidr for each subnet to avoid cidr duplicate
# The cidr starts from tenant_cidr
next_cidr = netaddr.IPNetwork(self.tenant_cidr)
@@ -301,9 +303,9 @@
)
test_routes.sort(key=lambda x: x['destination'])
- extra_route = self.client.update_extra_routes(router['id'],
- routes=test_routes)
- show_body = self.client.show_router(router['id'])
+ extra_route = self.routers_client.update_extra_routes(
+ router['id'], routes=test_routes)
+ show_body = self.routers_client.show_router(router['id'])
# Assert the number of routes
self.assertEqual(routes_num, len(extra_route['router']['routes']))
self.assertEqual(routes_num, len(show_body['router']['routes']))
@@ -323,18 +325,23 @@
routes[i]['destination'])
self.assertEqual(test_routes[i]['nexthop'], routes[i]['nexthop'])
+ self.routers_client.delete_extra_routes(router['id'])
+ show_body_after_deletion = self.routers_client.show_router(
+ router['id'])
+ self.assertEmpty(show_body_after_deletion['router']['routes'])
+
def _delete_extra_routes(self, router_id):
- self.client.delete_extra_routes(router_id)
+ self.routers_client.delete_extra_routes(router_id)
@test.idempotent_id('a8902683-c788-4246-95c7-ad9c6d63a4d9')
def test_update_router_admin_state(self):
router = self._create_router(data_utils.rand_name('router-'))
self.assertFalse(router['admin_state_up'])
# Update router admin state
- update_body = self.client.update_router(router['id'],
- admin_state_up=True)
+ update_body = self.routers_client.update_router(router['id'],
+ admin_state_up=True)
self.assertTrue(update_body['router']['admin_state_up'])
- show_body = self.client.show_router(router['id'])
+ show_body = self.routers_client.show_router(router['id'])
self.assertTrue(show_body['router']['admin_state_up'])
@test.attr(type='smoke')
@@ -381,21 +388,21 @@
@test.idempotent_id('141297aa-3424-455d-aa8d-f2d95731e00a')
def test_create_distributed_router(self):
name = data_utils.rand_name('router')
- create_body = self.admin_client.create_router(
+ create_body = self.admin_routers_client.create_router(
name, distributed=True)
self.addCleanup(self._delete_router,
create_body['router']['id'],
- self.admin_client)
+ self.admin_routers_client)
self.assertTrue(create_body['router']['distributed'])
@test.idempotent_id('644d7a4a-01a1-4b68-bb8d-0c0042cb1729')
def test_convert_centralized_router(self):
router = self._create_router(data_utils.rand_name('router'))
self.assertNotIn('distributed', router)
- update_body = self.admin_client.update_router(router['id'],
- distributed=True)
+ update_body = self.admin_routers_client.update_router(router['id'],
+ distributed=True)
self.assertTrue(update_body['router']['distributed'])
- show_body = self.admin_client.show_router(router['id'])
+ show_body = self.admin_routers_client.show_router(router['id'])
self.assertTrue(show_body['router']['distributed'])
- show_body = self.client.show_router(router['id'])
+ show_body = self.routers_client.show_router(router['id'])
self.assertNotIn('distributed', show_body['router'])
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 84dbd8d..36aaf2d 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -47,7 +47,7 @@
@test.idempotent_id('37a94fc0-a834-45b9-bd23-9a81d2fd1e22')
def test_router_add_gateway_invalid_network_returns_404(self):
self.assertRaises(lib_exc.NotFound,
- self.client.update_router,
+ self.routers_client.update_router,
self.router['id'],
external_gateway_info={
'network_id': self.router['id']})
@@ -60,7 +60,7 @@
sub_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
self.create_subnet(alt_network, cidr=sub_cidr)
self.assertRaises(lib_exc.BadRequest,
- self.client.update_router,
+ self.routers_client.update_router,
self.router['id'],
external_gateway_info={
'network_id': alt_network['id']})
@@ -84,31 +84,31 @@
@test.attr(type=['negative'])
@test.idempotent_id('04df80f9-224d-47f5-837a-bf23e33d1c20')
def test_router_remove_interface_in_use_returns_409(self):
- self.client.add_router_interface(self.router['id'],
- subnet_id=self.subnet['id'])
+ self.routers_client.add_router_interface(self.router['id'],
+ subnet_id=self.subnet['id'])
self.assertRaises(lib_exc.Conflict,
- self.client.delete_router,
+ self.routers_client.delete_router,
self.router['id'])
@test.attr(type=['negative'])
@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(lib_exc.NotFound, self.client.show_router,
+ self.assertRaises(lib_exc.NotFound, self.routers_client.show_router,
router)
@test.attr(type=['negative'])
@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(lib_exc.NotFound, self.client.update_router,
+ self.assertRaises(lib_exc.NotFound, self.routers_client.update_router,
router, name="new_name")
@test.attr(type=['negative'])
@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(lib_exc.NotFound, self.client.delete_router,
+ self.assertRaises(lib_exc.NotFound, self.routers_client.delete_router,
router)
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 5213c18..401fa3b 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -227,7 +227,7 @@
{'ethertype': 'IPv4',
'ip_prefix': CONF.network.tenant_network_v6_cidr})
for pair in pairs:
- self.assertRaisesRegexp(
+ self.assertRaisesRegex(
lib_exc.BadRequest,
"Conflicting value ethertype",
self.security_group_rules_client.create_security_group_rule,
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index d027132..c6cc8e2 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -30,7 +30,7 @@
Lists subnet pool.
Show subnet pool details.
- v2.0 of the Neutron API is assumed. It is assumed that subnetpools
+ v2.0 of the Neutron API is assumed. It is assumed that subnet_allocation
options mentioned in the [network-feature-enabled] section and
default_network option mentioned in the [network] section of
etc/tempest.conf:
@@ -40,8 +40,8 @@
@classmethod
def skip_checks(cls):
super(SubnetPoolsTestJSON, cls).skip_checks()
- if not test.is_extension_enabled('subnetpools', 'network'):
- msg = "subnet pools extension not enabled."
+ if not test.is_extension_enabled('subnet_allocation', 'network'):
+ msg = "subnet_allocation extension not enabled."
raise cls.skipException(msg)
@test.attr(type='smoke')
diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
index ffff580..61c271c 100644
--- a/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
+++ b/tempest/api/orchestration/stacks/templates/cinder_basic.yaml
@@ -1,10 +1,15 @@
heat_template_version: 2013-05-23
+parameters:
+ volume_size:
+ type: number
+ default: 1
+
resources:
volume:
type: OS::Cinder::Volume
properties:
- size: 1
+ size: { get_param: volume_size }
description: a descriptive description
name: volume_name
diff --git a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml b/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
index b660c19..0bc6d69 100644
--- a/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
+++ b/tempest/api/orchestration/stacks/templates/cinder_basic_delete_retain.yaml
@@ -1,11 +1,16 @@
heat_template_version: 2013-05-23
+parameters:
+ volume_size:
+ type: number
+ default: 1
+
resources:
volume:
deletion_policy: 'Retain'
type: OS::Cinder::Volume
properties:
- size: 1
+ size: { get_param: volume_size }
description: a descriptive description
name: volume_name
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 001bc08..5483361 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -151,7 +151,7 @@
def test_created_router(self):
"""Verifies created router."""
router_id = self.test_resources.get('Router')['physical_resource_id']
- body = self.network_client.show_router(router_id)
+ body = self.routers_client.show_router(router_id)
router = body['router']
self.assertEqual(self.neutron_basic_template['resources'][
'Router']['properties']['name'], router['name'])
diff --git a/tempest/api/orchestration/stacks/test_volumes.py b/tempest/api/orchestration/stacks/test_volumes.py
index 37e68ef..a5aaf6e 100644
--- a/tempest/api/orchestration/stacks/test_volumes.py
+++ b/tempest/api/orchestration/stacks/test_volumes.py
@@ -32,8 +32,7 @@
self.assertIsNotNone(volume_id)
volume = self.volumes_client.show_volume(volume_id)['volume']
self.assertEqual('available', volume.get('status'))
- self.assertEqual(template['resources']['volume']['properties'][
- 'size'], volume.get('size'))
+ self.assertEqual(CONF.volume.volume_size, volume.get('size'))
# Some volume properties have been renamed with Cinder v2
if CONF.volume_feature_enabled.api_v2:
@@ -51,8 +50,8 @@
def _outputs_verify(self, stack_identifier, template):
self.assertEqual('available',
self.get_stack_output(stack_identifier, 'status'))
- self.assertEqual(str(template['resources']['volume']['properties'][
- 'size']), self.get_stack_output(stack_identifier, 'size'))
+ self.assertEqual(str(CONF.volume.volume_size),
+ self.get_stack_output(stack_identifier, 'size'))
self.assertEqual(template['resources']['volume']['properties'][
'description'], self.get_stack_output(stack_identifier,
'display_description'))
@@ -65,7 +64,12 @@
"""Create and delete a volume via OS::Cinder::Volume."""
stack_name = data_utils.rand_name('heat')
template = self.read_template('cinder_basic')
- stack_identifier = self.create_stack(stack_name, template)
+ stack_identifier = self.create_stack(
+ stack_name,
+ template,
+ parameters={
+ 'volume_size': CONF.volume.volume_size
+ })
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# Verify with cinder that the volume exists, with matching details
@@ -94,7 +98,12 @@
"""Ensure the 'Retain' deletion policy is respected."""
stack_name = data_utils.rand_name('heat')
template = self.read_template('cinder_basic_delete_retain')
- stack_identifier = self.create_stack(stack_name, template)
+ stack_identifier = self.create_stack(
+ stack_name,
+ template,
+ parameters={
+ 'volume_size': CONF.volume.volume_size
+ })
self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
# Verify with cinder that the volume exists, with matching details
diff --git a/tempest/api/utils.py b/tempest/api/utils.py
deleted file mode 100644
index 00c93b7..0000000
--- a/tempest/api/utils.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Common utilities used in testing."""
-
-from tempest import test
-
-
-class skip_unless_attr(object):
- """Decorator that skips a test if a specified attr exists and is True."""
- def __init__(self, attr, msg=None):
- self.attr = attr
- self.message = msg or ("Test case attribute %s not found "
- "or False") % attr
-
- def __call__(self, func):
- def _skipper(*args, **kw):
- """Wrapped skipper function."""
- testobj = args[0]
- if not getattr(testobj, self.attr, False):
- raise test.BaseTestCase.skipException(self.message)
- func(*args, **kw)
- _skipper.__name__ = func.__name__
- _skipper.__doc__ = func.__doc__
- return _skipper
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 47130de..755365d 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -12,9 +12,6 @@
# 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.api.volume import base
from tempest import config
from tempest import test
@@ -23,6 +20,12 @@
CONF = config.CONF
+def _get_host(host):
+ if CONF.volume_feature_enabled.volume_services:
+ host = host.split('@')[0]
+ return host
+
+
class VolumesServicesV2TestJSON(base.BaseVolumeAdminTest):
"""Tests Volume Services API.
@@ -34,7 +37,10 @@
super(VolumesServicesV2TestJSON, cls).resource_setup()
cls.services = (cls.admin_volume_services_client.list_services()
['services'])
- cls.host_name = cls.services[0]['host']
+ # NOTE: Cinder service-list API returns the list contains
+ # "<host name>@<driver name>" like "nova-compute01@lvmdriver-1".
+ # So here picks <host name> up as a host.
+ cls.host_name = _get_host(cls.services[0]['host'])
cls.binary_name = cls.services[0]['binary']
@test.idempotent_id('e0218299-0a59-4f43-8b2b-f1c035b3d26d')
@@ -51,16 +57,10 @@
for service in services:
self.assertEqual(self.binary_name, service['binary'])
- @decorators.skip_because(bug="1530144")
@test.idempotent_id('178710e4-7596-4e08-9333-745cb8bc4f8d')
def test_get_service_by_host_name(self):
- def get_host(host):
- if CONF.volume_feature_enabled.volume_services:
- host = host.split('@')[0]
- return host
-
services_on_host = [service for service in self.services if
- get_host(service['host']) == self.host_name]
+ _get_host(service['host']) == self.host_name]
services = (self.admin_volume_services_client.list_services(
host=self.host_name)['services'])
@@ -80,7 +80,7 @@
host=self.host_name, binary=self.binary_name))['services']
self.assertEqual(1, len(services))
- self.assertEqual(self.host_name, services[0]['host'])
+ self.assertEqual(self.host_name, _get_host(services[0]['host']))
self.assertEqual(self.binary_name, services[0]['binary'])
diff --git a/tempest/clients.py b/tempest/clients.py
index e85a683..8931706 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -103,38 +103,35 @@
DatabaseLimitsClient
from tempest.services.database.json.versions_client import \
DatabaseVersionsClient
-from tempest.services.identity.v2.json.endpoints_client import \
- EndpointsClient as EndpointsV2Client
-from tempest.services.identity.v2.json.identity_client import \
- IdentityClient
-from tempest.services.identity.v2.json.roles_client import \
- RolesClient
+from tempest.services.identity.v2.json.endpoints_client import EndpointsClient
+from tempest.services.identity.v2.json.identity_client import IdentityClient
+from tempest.services.identity.v2.json.roles_client import RolesClient
from tempest.services.identity.v2.json.services_client import \
- ServicesClient as ServicesV2Client
-from tempest.services.identity.v2.json.tenants_client import \
- TenantsClient
-from tempest.services.identity.v2.json.users_client import \
- UsersClient
+ ServicesClient as IdentityServicesClient
+from tempest.services.identity.v2.json.tenants_client import TenantsClient
+from tempest.services.identity.v2.json.users_client import UsersClient
from tempest.services.identity.v3.json.credentials_client import \
- CredentialsClient as CredentialsV3Client
+ CredentialsClient
from tempest.services.identity.v3.json.domains_client import DomainsClient
from tempest.services.identity.v3.json.endpoints_client import \
- EndPointClient as EndPointV3Client
-from tempest.services.identity.v3.json.groups_client import \
- GroupsClient as GroupsV3Client
-from tempest.services.identity.v3.json.identity_client import IdentityV3Client
-from tempest.services.identity.v3.json.policies_client import \
- PoliciesClient as PoliciesV3Client
+ EndPointsClient as EndPointsV3Client
+from tempest.services.identity.v3.json.groups_client import GroupsClient
+from tempest.services.identity.v3.json.identity_client import \
+ IdentityClient as IdentityV3Client
+from tempest.services.identity.v3.json.policies_client import PoliciesClient
from tempest.services.identity.v3.json.projects_client import ProjectsClient
-from tempest.services.identity.v3.json.regions_client import \
- RegionsClient as RegionsV3Client
+from tempest.services.identity.v3.json.regions_client import RegionsClient
+from tempest.services.identity.v3.json.roles_client import \
+ RolesClient as RolesV3Client
from tempest.services.identity.v3.json.services_client import \
ServicesClient as IdentityServicesV3Client
from tempest.services.identity.v3.json.trusts_client import TrustsClient
-from tempest.services.identity.v3.json.users_clients import UsersV3Client
+from tempest.services.identity.v3.json.users_clients import \
+ UsersClient as UsersV3Client
from tempest.services.image.v1.json.images_client import ImagesClient
from tempest.services.image.v2.json.images_client import ImagesClientV2
from tempest.services.network.json.network_client import NetworkClient
+from tempest.services.network.json.routers_client import RoutersClient
from tempest.services.network.json.security_group_rules_client import \
SecurityGroupRulesClient
from tempest.services.object_storage.account_client import AccountClient
@@ -312,6 +309,14 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**self.default_params)
+ self.routers_client = RoutersClient(
+ self.auth_provider,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **self.default_params)
self.security_group_rules_client = SecurityGroupRulesClient(
self.auth_provider,
CONF.network.catalog_type,
@@ -484,18 +489,16 @@
# Clients below use the admin endpoint type of Keystone API v2
params_v2_admin = params.copy()
params_v2_admin['endpoint_type'] = CONF.identity.v2_admin_endpoint_type
- self.endpoints_v2_client = EndpointsV2Client(self.auth_provider,
- **params_v2_admin)
+ self.endpoints_client = EndpointsClient(self.auth_provider,
+ **params_v2_admin)
self.identity_client = IdentityClient(self.auth_provider,
**params_v2_admin)
self.tenants_client = TenantsClient(self.auth_provider,
**params_v2_admin)
- self.roles_client = RolesClient(self.auth_provider,
- **params_v2_admin)
- self.users_client = UsersClient(self.auth_provider,
- **params_v2_admin)
- self.services_v2_client = ServicesV2Client(self.auth_provider,
- **params_v2_admin)
+ self.roles_client = RolesClient(self.auth_provider, **params_v2_admin)
+ self.users_client = UsersClient(self.auth_provider, **params_v2_admin)
+ self.identity_services_client = IdentityServicesClient(
+ self.auth_provider, **params_v2_admin)
# Clients below use the public endpoint type of Keystone API v2
params_v2_public = params.copy()
@@ -517,17 +520,17 @@
**params_v3)
self.trusts_client = TrustsClient(self.auth_provider, **params_v3)
self.users_v3_client = UsersV3Client(self.auth_provider, **params_v3)
- self.endpoints_client = EndPointV3Client(self.auth_provider,
- **params_v3)
- self.identity_services_client = IdentityServicesV3Client(
+ self.endpoints_v3_client = EndPointsV3Client(self.auth_provider,
+ **params_v3)
+ self.roles_v3_client = RolesV3Client(self.auth_provider, **params_v3)
+ self.identity_services_v3_client = IdentityServicesV3Client(
self.auth_provider, **params_v3)
- self.policies_client = PoliciesV3Client(self.auth_provider,
- **params_v3)
+ self.policies_client = PoliciesClient(self.auth_provider, **params_v3)
self.projects_client = ProjectsClient(self.auth_provider, **params_v3)
- self.regions_client = RegionsV3Client(self.auth_provider, **params_v3)
- self.credentials_client = CredentialsV3Client(self.auth_provider,
- **params_v3)
- self.groups_client = GroupsV3Client(self.auth_provider, **params_v3)
+ self.regions_client = RegionsClient(self.auth_provider, **params_v3)
+ self.credentials_client = CredentialsClient(self.auth_provider,
+ **params_v3)
+ self.groups_client = GroupsClient(self.auth_provider, **params_v3)
# Token clients do not use the catalog. They only need default_params.
# They read auth_url, so they should only be set if the corresponding
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index df2d4b5..03dfd7b 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -104,6 +104,7 @@
from tempest.services.identity.v2.json import tenants_client
from tempest.services.identity.v2.json import users_client
from tempest.services.network.json import network_client
+from tempest.services.network.json import routers_client
LOG = None
CONF = config.CONF
@@ -171,6 +172,7 @@
)
network_admin = None
networks_admin = None
+ routers_admin = None
subnets_admin = None
neutron_iso_networks = False
if (CONF.service_available.neutron and
@@ -188,6 +190,12 @@
CONF.network.region or CONF.identity.region,
endpoint_type='adminURL',
**params)
+ routers_admin = routers_client.RoutersClient(
+ _auth,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type='adminURL',
+ **params)
subnets_admin = subnets_client.SubnetsClient(
_auth,
CONF.network.catalog_type,
@@ -195,12 +203,13 @@
endpoint_type='adminURL',
**params)
return (identity_admin, tenants_admin, roles_admin, users_admin,
- neutron_iso_networks, network_admin, networks_admin, subnets_admin)
+ neutron_iso_networks, network_admin, networks_admin, routers_admin,
+ subnets_admin)
def create_resources(opts, resources):
(identity_admin, tenants_admin, roles_admin, users_admin,
- neutron_iso_networks, network_admin, networks_admin,
+ neutron_iso_networks, network_admin, networks_admin, routers_admin,
subnets_admin) = get_admin_clients(opts)
roles = roles_admin.list_roles()['roles']
for u in resources['users']:
@@ -246,8 +255,8 @@
for u in resources['users']:
tenant = identity.get_tenant_by_name(tenants_admin, u['tenant'])
network_name, router_name = create_network_resources(
- network_admin, networks_admin, subnets_admin, tenant['id'],
- u['name'])
+ network_admin, networks_admin, routers_admin, subnets_admin,
+ tenant['id'], u['name'])
u['network'] = network_name
u['router'] = router_name
LOG.info('Networks created')
@@ -274,7 +283,8 @@
def create_network_resources(network_admin_client, networks_admin_client,
- subnets_admin_client, tenant_id, name):
+ routers_admin_client, subnets_admin_client,
+ tenant_id, name):
def _create_network(name):
resp_body = networks_admin_client.create_network(
@@ -305,14 +315,14 @@
def _create_router(router_name):
external_net_id = dict(
network_id=CONF.network.public_network_id)
- resp_body = network_admin_client.create_router(
+ resp_body = routers_admin_client.create_router(
router_name,
external_gateway_info=external_net_id,
tenant_id=tenant_id)
return resp_body['router']
def _add_router_interface(router_id, subnet_id):
- network_admin_client.add_router_interface(router_id,
+ routers_admin_client.add_router_interface(router_id,
subnet_id=subnet_id)
network_name = name + "-network"
@@ -480,8 +490,8 @@
def main(opts=None):
setup_logging()
if not opts:
- LOG.warn("Use of: 'tempest-account-generator' is deprecated, "
- "please use: 'tempest account-generator'")
+ LOG.warning("Use of: 'tempest-account-generator' is deprecated, "
+ "please use: 'tempest account-generator'")
opts = get_options()
if opts.config_file:
config.CONF.set_config_path(opts.config_file)
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 5a52043..3706b54 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -117,7 +117,6 @@
if is_dry_run:
self.dry_run_data["_tenants_to_clean"] = {}
- f = open(DRY_RUN_JSON, 'w+')
admin_mgr = self.admin_mgr
# Always cleanup tempest and alt tempest tenants unless
@@ -146,9 +145,9 @@
svc.run()
if is_dry_run:
- f.write(json.dumps(self.dry_run_data, sort_keys=True,
- indent=2, separators=(',', ': ')))
- f.close()
+ with open(DRY_RUN_JSON, 'w+') as f:
+ f.write(json.dumps(self.dry_run_data, sort_keys=True,
+ indent=2, separators=(',', ': ')))
self._remove_admin_user_roles()
@@ -281,16 +280,15 @@
svc = service(admin_mgr, **kwargs)
svc.run()
- f = open(SAVED_STATE_JSON, 'w+')
- f.write(json.dumps(data,
- sort_keys=True, indent=2, separators=(',', ': ')))
- f.close()
+ with open(SAVED_STATE_JSON, 'w+') as f:
+ f.write(json.dumps(data,
+ sort_keys=True, indent=2, separators=(',', ': ')))
def _load_json(self):
try:
- json_file = open(SAVED_STATE_JSON)
- self.json_data = json.load(json_file)
- json_file.close()
+ with open(SAVED_STATE_JSON) as json_file:
+ self.json_data = json.load(json_file)
+
except IOError as ex:
LOG.exception("Failed loading saved state, please be sure you"
" have first run cleanup with --init-saved-state "
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 0640a4e..a0676b6 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -390,6 +390,7 @@
self.metering_labels_client = manager.metering_labels_client
self.metering_label_rules_client = manager.metering_label_rules_client
self.security_groups_client = manager.security_groups_client
+ self.routers_client = manager.routers_client
def _filter_by_conf_networks(self, item_list):
if not item_list or not all(('network_id' in i for i in item_list)):
@@ -449,7 +450,7 @@
class NetworkRouterService(NetworkService):
def list(self):
- client = self.client
+ client = self.routers_client
routers = client.list_routers(**self.tenant_filter)
routers = routers['routers']
if self.is_preserve:
@@ -460,7 +461,7 @@
return routers
def delete(self):
- client = self.client
+ client = self.routers_client
routers = self.list()
for router in routers:
try:
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index e474d86..48c06ff 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -134,6 +134,7 @@
from tempest.services.identity.v2.json import users_client
from tempest.services.image.v2.json import images_client
from tempest.services.network.json import network_client
+from tempest.services.network.json import routers_client
from tempest.services.object_storage import container_client
from tempest.services.object_storage import object_client
from tempest.services.telemetry.json import alarming_client
@@ -270,6 +271,14 @@
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**default_params)
+ self.routers = routers_client.RoutersClient(
+ _auth,
+ CONF.network.catalog_type,
+ CONF.network.region or CONF.identity.region,
+ endpoint_type=CONF.network.endpoint_type,
+ build_interval=CONF.network.build_interval,
+ build_timeout=CONF.network.build_timeout,
+ **default_params)
self.subnets = subnets_client.SubnetsClient(
_auth,
CONF.network.catalog_type,
@@ -739,7 +748,7 @@
def _get_router_namespace(client, network):
network_id = _get_resource_by_name(client.networks,
'networks', network)['id']
- n_body = client.networks.list_routers()
+ n_body = client.routers.list_routers()
for router in n_body['routers']:
router_id = router['id']
r_body = client.networks.list_router_interfaces(router_id)
@@ -756,7 +765,7 @@
# we cannot assume they all have the same signature so we need to discard
# the unused response first value it two values are being returned.
body = get_resources()
- if type(body) == tuple:
+ if isinstance(body, tuple):
body = body[1]
if isinstance(body, dict):
body = body[resource]
@@ -824,7 +833,7 @@
client = client_for_user(router['owner'])
# only create a router if the name isn't here
- body = client.networks.list_routers()
+ body = client.routers.list_routers()
if any(item['name'] == router['name'] for item in body['routers']):
LOG.warning("Duplicated router name: %s" % router['name'])
continue
@@ -841,9 +850,9 @@
for subnet in router['subnet']:
subnet_id = _get_resource_by_name(client.networks,
'subnets', subnet)['id']
- client.networks.remove_router_interface(router_id,
- subnet_id=subnet_id)
- client.networks.delete_router(router_id)
+ client.routers.remove_router_interface(router_id,
+ subnet_id=subnet_id)
+ client.routers.delete_router(router_id)
def add_router_interface(routers):
@@ -856,13 +865,13 @@
subnet_id = _get_resource_by_name(client.networks,
'subnets', subnet)['id']
# connect routers to their subnets
- client.networks.add_router_interface(router_id,
- subnet_id=subnet_id)
+ client.routers.add_router_interface(router_id,
+ subnet_id=subnet_id)
# connect routers to external network if set to "gateway"
if router['gateway']:
if CONF.network.public_network_id:
ext_net = CONF.network.public_network_id
- client.networks._update_router(
+ client.routers._update_router(
router_id, set_enable_snat=True,
external_gateway_info={"network_id": ext_net})
else:
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 5e5e127..9049886 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -354,8 +354,6 @@
outfile = sys.stdout
if update:
conf_file = _get_config_file()
- if opts.output:
- outfile = open(opts.output, 'w+')
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
@@ -378,8 +376,9 @@
display_results(results, update, replace)
if update:
conf_file.close()
- CONF_PARSER.write(outfile)
- outfile.close()
+ if opts.output:
+ with open(opts.output, 'w+') as outfile:
+ CONF_PARSER.write(outfile)
finally:
icreds.clear_creds()
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index b14012e..2d2909a 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -17,9 +17,9 @@
from oslo_utils import excutils
from tempest.common import fixed_network
-from tempest.common import service_client
from tempest.common import waiters
from tempest import config
+from tempest.lib.common import rest_client
from tempest.lib.common.utils import data_utils
CONF = config.CONF
@@ -49,10 +49,6 @@
# TODO(jlanoux) add support of wait_until PINGABLE/SSHABLE
- name = name
- flavor = flavor
- image_id = image_id
-
if name is None:
name = data_utils.rand_name(__name__ + "-instance")
if flavor is None:
@@ -129,7 +125,7 @@
servers = \
[s for s in body_servers['servers'] if s['name'].startswith(name)]
else:
- body = service_client.ResponseBody(body.response, body['server'])
+ body = rest_client.ResponseBody(body.response, body['server'])
servers = [body]
# The name of the method to associate a floating IP to as server is too
@@ -152,14 +148,12 @@
except Exception:
with excutils.save_and_reraise_exception():
- if ('preserve_server_on_error' not in kwargs
- or kwargs['preserve_server_on_error'] is False):
- for server in servers:
- try:
- clients.servers_client.delete_server(
- server['id'])
- except Exception:
- LOG.exception('Deleting server %s failed'
- % server['id'])
+ for server in servers:
+ try:
+ clients.servers_client.delete_server(
+ server['id'])
+ except Exception:
+ LOG.exception('Deleting server %s failed'
+ % server['id'])
return body, servers
diff --git a/tempest/common/cred_client.py b/tempest/common/cred_client.py
index edc51ca..37c9727 100644
--- a/tempest/common/cred_client.py
+++ b/tempest/common/cred_client.py
@@ -32,14 +32,12 @@
"""
def __init__(self, identity_client, projects_client, users_client,
- roles_client=None):
+ roles_client):
# The client implies version and credentials
self.identity_client = identity_client
self.users_client = users_client
self.projects_client = projects_client
- # this is temporary until the v3 clients are
- # separated, then using *only* each client will become mandatory
- self.roles_client = roles_client or identity_client
+ self.roles_client = roles_client
def create_user(self, username, password, project, email):
user = self.users_client.create_user(
@@ -130,9 +128,9 @@
class V3CredsClient(CredsClient):
def __init__(self, identity_client, projects_client, users_client,
- domains_client, domain_name):
+ roles_client, domains_client, domain_name):
super(V3CredsClient, self).__init__(identity_client, projects_client,
- users_client)
+ users_client, roles_client)
self.domains_client = domains_client
try:
@@ -167,10 +165,6 @@
project_domain_id=self.creds_domain['id'],
project_domain_name=self.creds_domain['name'])
- def _list_roles(self):
- roles = self.identity_client.list_roles()['roles']
- return roles
-
def _assign_user_role(self, project, user, role):
self.roles_client.assign_user_role_on_project(project['id'],
user['id'],
@@ -180,7 +174,7 @@
def get_creds_client(identity_client,
projects_client,
users_client,
- roles_client=None,
+ roles_client,
domains_client=None,
project_domain_name=None):
if isinstance(identity_client, v2_identity.IdentityClient):
@@ -188,4 +182,4 @@
roles_client)
else:
return V3CredsClient(identity_client, projects_client, users_client,
- domains_client, project_domain_name)
+ roles_client, domains_client, project_domain_name)
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index a254211..2ffc92d 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -64,6 +64,7 @@
self.domains_admin_client,
self.network_admin_client,
self.networks_admin_client,
+ self.routers_admin_client,
self.subnets_admin_client,
self.ports_admin_client,
self.security_groups_admin_client) = self._get_admin_clients()
@@ -93,13 +94,14 @@
if self.identity_version == 'v2':
return (os.identity_client, os.tenants_client, os.users_client,
os.roles_client, None, os.network_client,
- os.networks_client, os.subnets_client, os.ports_client,
- os.security_groups_client)
+ os.networks_client, os.routers_client, os.subnets_client,
+ os.ports_client, os.security_groups_client)
else:
return (os.identity_v3_client, os.projects_client,
- os.users_v3_client, None, os.domains_client,
- os.network_client, os.networks_client, os.subnets_client,
- os.ports_client, os.security_groups_client)
+ os.users_v3_client, os.roles_v3_client, os.domains_client,
+ os.network_client, os.networks_client, os.routers_client,
+ os.subnets_client, os.ports_client,
+ os.security_groups_client)
def _create_creds(self, suffix="", admin=False, roles=None):
"""Create random credentials under the following schema.
@@ -184,12 +186,19 @@
router = self._create_router(router_name, tenant_id)
self._add_router_interface(router['id'], subnet['id'])
except Exception:
- if router:
- self._clear_isolated_router(router['id'], router['name'])
- if subnet:
- self._clear_isolated_subnet(subnet['id'], subnet['name'])
- if network:
- self._clear_isolated_network(network['id'], network['name'])
+ try:
+ if router:
+ self._clear_isolated_router(router['id'], router['name'])
+ if subnet:
+ self._clear_isolated_subnet(subnet['id'], subnet['name'])
+ if network:
+ self._clear_isolated_network(network['id'],
+ network['name'])
+ except Exception as cleanup_exception:
+ msg = "There was an exception trying to setup network " \
+ "resources for tenant %s, and this error happened " \
+ "trying to clean them up: %s"
+ LOG.warning(msg % (tenant_id, cleanup_exception))
raise
return network, subnet, router
@@ -230,14 +239,14 @@
def _create_router(self, router_name, tenant_id):
external_net_id = dict(
network_id=CONF.network.public_network_id)
- resp_body = self.network_admin_client.create_router(
+ resp_body = self.routers_admin_client.create_router(
router_name,
external_gateway_info=external_net_id,
tenant_id=tenant_id)
return resp_body['router']
def _add_router_interface(self, router_id, subnet_id):
- self.network_admin_client.add_router_interface(router_id,
+ self.routers_admin_client.add_router_interface(router_id,
subnet_id=subnet_id)
def get_credentials(self, credential_type):
@@ -288,9 +297,9 @@
return self.get_credentials(roles)
def _clear_isolated_router(self, router_id, router_name):
- net_client = self.network_admin_client
+ client = self.routers_admin_client
try:
- net_client.delete_router(router_id)
+ client.delete_router(router_id)
except lib_exc.NotFound:
LOG.warning('router with name: %s not found for delete' %
router_name)
@@ -324,7 +333,7 @@
(secgroup['name'], secgroup['id']))
def _clear_isolated_net_resources(self):
- net_client = self.network_admin_client
+ client = self.routers_admin_client
for cred in self._creds:
creds = self._creds.get(cred)
if (not creds or not any([creds.router, creds.network,
@@ -337,7 +346,7 @@
if (not self.network_resources or
(self.network_resources.get('router') and creds.subnet)):
try:
- net_client.remove_router_interface(
+ client.remove_router_interface(
creds.router['id'],
subnet_id=creds.subnet['id'])
except lib_exc.NotFound:
diff --git a/tempest/common/negative_rest_client.py b/tempest/common/negative_rest_client.py
index d97411c..3495a24 100644
--- a/tempest/common/negative_rest_client.py
+++ b/tempest/common/negative_rest_client.py
@@ -15,30 +15,19 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common import service_client
from tempest import config
+from tempest.lib.common import rest_client
CONF = config.CONF
-class NegativeRestClient(service_client.ServiceClient):
+class NegativeRestClient(rest_client.RestClient):
"""Version of RestClient that does not raise exceptions."""
- def __init__(self, auth_provider, service,
- build_interval=None, build_timeout=None,
- disable_ssl_certificate_validation=None,
- ca_certs=None, trace_requests=None):
+ def __init__(self, auth_provider, service, **kwargs):
region, endpoint_type = self._get_region_and_endpoint_type(service)
super(NegativeRestClient, self).__init__(
- auth_provider,
- service,
- 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,
- trace_requests=trace_requests)
+ auth_provider, service, region, endpoint_type=endpoint_type,
+ **kwargs)
def _get_region_and_endpoint_type(self, service):
"""Returns the region for a specific service"""
diff --git a/tempest/common/service_client.py b/tempest/common/service_client.py
deleted file mode 100644
index 14a3bd6..0000000
--- a/tempest/common/service_client.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.lib.common import rest_client
-
-
-class ServiceClient(rest_client.RestClient):
-
- def __init__(self, auth_provider, service, region,
- endpoint_type=None, build_interval=None, build_timeout=None,
- disable_ssl_certificate_validation=None, ca_certs=None,
- trace_requests=None):
-
- dscv = disable_ssl_certificate_validation
- params = {
- 'disable_ssl_certificate_validation': dscv,
- 'ca_certs': ca_certs,
- 'trace_requests': trace_requests
- }
-
- if endpoint_type is not None:
- params.update({'endpoint_type': endpoint_type})
- if build_interval is not None:
- params.update({'build_interval': build_interval})
- if build_timeout is not None:
- params.update({'build_timeout': build_timeout})
- super(ServiceClient, self).__init__(auth_provider, service, region,
- **params)
-
-
-class ResponseBody(dict):
- """Class that wraps an http response and dict body into a single value.
-
- Callers that receive this object will normally use it as a dict but
- can extract the response if needed.
- """
-
- def __init__(self, response, body=None):
- body_data = body or {}
- self.update(body_data)
- self.response = response
-
- def __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.
-
- Callers that receive this object will normally use it as a list but
- can extract the response if needed.
- """
-
- def __init__(self, response, body=None):
- body_data = body or []
- self.extend(body_data)
- self.response = response
-
- def __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 cfd9df6..36e3e3a 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -102,7 +102,12 @@
cmd = "ip addr %s| awk '/ether/ {print $2}'" % show_nic
return self.exec_command(cmd).strip().lower()
- def get_nic_name(self, address):
+ def get_nic_name_by_mac(self, address):
+ cmd = "ip -o link | awk '/%s/ {print $2}'" % address
+ nic = self.exec_command(cmd)
+ return nic.strip().strip(":").lower()
+
+ def get_nic_name_by_ip(self, address):
cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
nic = self.exec_command(cmd)
return nic.strip().strip(":").lower()
@@ -142,7 +147,7 @@
def _renew_lease_udhcpc(self, fixed_ip=None):
"""Renews DHCP lease via udhcpc client. """
file_path = '/var/run/udhcpc.'
- nic_name = self.get_nic_name(fixed_ip)
+ nic_name = self.get_nic_name_by_ip(fixed_ip)
pid = self.exec_command('cat {path}{nic}.pid'.
format(path=file_path, nic=nic_name))
pid = pid.strip()
diff --git a/tempest/config.py b/tempest/config.py
index b062201..4c3b04b 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -281,13 +281,7 @@
help=('The minimum number of compute nodes expected. This will '
'be utilized by some multinode specific tests to ensure '
'that requests match the expected size of the cluster '
- 'you are testing with.'))
-]
-
-compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
- title="Enabled Compute Service Features")
-
-ComputeFeaturesGroup = [
+ 'you are testing with.')),
cfg.StrOpt('min_microversion',
default=None,
help="Lower version of the test target microversion range. "
@@ -296,7 +290,8 @@
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
- "with format 'X.Y' or string 'latest'"),
+ "with format 'X.Y' or string 'latest'",
+ deprecated_group='compute-feature-enabled'),
cfg.StrOpt('max_microversion',
default=None,
help="Upper version of the test target microversion range. "
@@ -305,7 +300,14 @@
"min_microversion and max_microversion. "
"If both values are not specified, Tempest avoids tests "
"which require a microversion. Valid values are string "
- "with format 'X.Y' or string 'latest'"),
+ "with format 'X.Y' or string 'latest'",
+ deprecated_group='compute-feature-enabled'),
+]
+
+compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
+ title="Enabled Compute Service Features")
+
+ComputeFeaturesGroup = [
cfg.BoolOpt('disk_config',
default=True,
help="If false, skip disk config tests"),
@@ -404,6 +406,15 @@
cfg.BoolOpt('config_drive',
default=True,
help='Enable special configuration drive with metadata.'),
+ cfg.ListOpt('scheduler_available_filters',
+ default=['all'],
+ help="A list of enabled filters that nova will accept as hints"
+ " to the scheduler when creating a server. A special "
+ "entry 'all' indicates all filters are enabled. Empty "
+ "list indicates all filters are disabled. The full "
+ "available list of filters is in nova.conf: "
+ "DEFAULT.scheduler_available_filters"),
+
]
@@ -953,7 +964,7 @@
DataProcessingFeaturesGroup = [
cfg.ListOpt('plugins',
- default=["vanilla", "hdp"],
+ default=["vanilla", "cdh"],
deprecated_group="data_processing-feature-enabled",
help="List of enabled data processing plugins")
]
@@ -1027,11 +1038,6 @@
default='cirros-0.3.1-x86_64-vmlinuz',
help='AKI image file name',
deprecated_for_removal=True),
- cfg.IntOpt(
- 'large_ops_number',
- default=0,
- help="specifies how many resources to request at once. Used "
- "for large operations testing."),
# TODO(yfried): add support for dhcpcd
cfg.StrOpt('dhcp_client',
default='udhcpc',
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 86e8460..031df7f 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -176,20 +176,6 @@
message = "Invalid structure of table with details"
-class InvalidAPIVersionString(TempestException):
- message = ("API Version String %(version)s is of invalid format. Must "
- "be of format MajorNum.MinorNum or string 'latest'.")
-
-
-class JSONSchemaNotFound(TempestException):
- message = ("JSON Schema for %(version)s is not found in \n"
- " %(schema_versions_info)s")
-
-
-class InvalidAPIVersionRange(TempestException):
- message = ("API Min Version is greater than Max version")
-
-
class CommandFailed(Exception):
def __init__(self, returncode, cmd, output, stderr):
super(CommandFailed, self).__init__()
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index 50a5477..5d3fc93 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -5,3 +5,4 @@
./tempest/services/volume/base/base_backups_client.py
./tempest/services/baremetal/base.py
./tempest/services/network/json/network_client.py
+./tempest/services/network/json/routers_client.py
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index 485c51a..3289f04 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -267,12 +267,13 @@
'type': 'object',
'properties': {
'id': {'type': 'string'},
- 'device': {'type': 'string'},
+ 'device': {'type': ['string', 'null']},
'volumeId': {'type': 'string'},
'serverId': {'type': ['integer', 'string']}
},
'additionalProperties': False,
- 'required': ['id', 'device', 'volumeId', 'serverId']
+ # 'device' is optional in response.
+ 'required': ['id', 'volumeId', 'serverId']
}
attach_volume = {
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 806acb5..71c4f4f 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -319,17 +319,30 @@
_base_url = ep['endpoints'][0].get(endpoint_type)
break
if _base_url is None:
- raise exceptions.EndpointNotFound(service)
+ raise exceptions.EndpointNotFound(
+ "service: %s, region: %s, endpoint_type: %s" %
+ (service, region, endpoint_type))
parts = urlparse.urlparse(_base_url)
if filters.get('api_version', None) is not None:
- path = "/" + filters['api_version']
- noversion_path = "/".join(parts.path.split("/")[2:])
- if noversion_path != "":
- path += "/" + noversion_path
- _base_url = _base_url.replace(parts.path, path)
+ version_path = '/%s' % filters['api_version']
+ path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
+ version_path,
+ parts.path,
+ count=1)
+ _base_url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ path or version_path,
+ parts.params,
+ parts.query,
+ parts.fragment))
if filters.get('skip_path', None) is not None and parts.path != '':
- _base_url = _base_url.replace(parts.path, "/")
+ _base_url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ '/',
+ parts.params,
+ parts.query,
+ parts.fragment))
return _base_url
@@ -445,13 +458,24 @@
parts = urlparse.urlparse(_base_url)
if filters.get('api_version', None) is not None:
- path = "/" + filters['api_version']
- noversion_path = "/".join(parts.path.split("/")[2:])
- if noversion_path != "":
- path += "/" + noversion_path
- _base_url = _base_url.replace(parts.path, path)
+ version_path = '/%s' % filters['api_version']
+ path = re.sub(r'(^|/)+v\d+(?:\.\d+)?',
+ version_path,
+ parts.path,
+ count=1)
+ _base_url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ path or version_path,
+ parts.params,
+ parts.query,
+ parts.fragment))
if filters.get('skip_path', None) is not None:
- _base_url = _base_url.replace(parts.path, "/")
+ _base_url = urlparse.urlunparse((parts.scheme,
+ parts.netloc,
+ '/',
+ parts.params,
+ parts.query,
+ parts.fragment))
return _base_url
@@ -598,6 +622,9 @@
return None not in (self.username, self.password)
+COLLISIONS = [('project_name', 'tenant_name'), ('project_id', 'tenant_id')]
+
+
class KeystoneV3Credentials(Credentials):
"""Credentials suitable for the Keystone Identity V3 API"""
@@ -606,6 +633,16 @@
'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
'user_domain_name', 'user_id']
+ def _apply_credentials(self, attr):
+ for (key1, key2) in COLLISIONS:
+ val1 = attr.get(key1)
+ val2 = attr.get(key2)
+ if val1 and val2 and val1 != val2:
+ msg = ('Cannot have conflicting values for %s and %s' %
+ (key1, key2))
+ raise exceptions.InvalidCredentials(msg)
+ super(KeystoneV3Credentials, self)._apply_credentials(attr)
+
def __setattr__(self, key, value):
parent = super(KeystoneV3Credentials, self)
# for tenant_* set both project and tenant
@@ -633,8 +670,10 @@
parent.__setattr__('user_domain_name', value)
# support domain_name coming from config
if key == 'domain_name':
- parent.__setattr__('user_domain_name', value)
- parent.__setattr__('project_domain_name', value)
+ if self.user_domain_name is None:
+ parent.__setattr__('user_domain_name', value)
+ if self.project_domain_name is None:
+ parent.__setattr__('project_domain_name', value)
# finally trigger default behaviour for all attributes
parent.__setattr__(key, value)
diff --git a/tempest/lib/cmd/check_uuid.py b/tempest/lib/cmd/check_uuid.py
index 3adeecd..be3aa49 100755
--- a/tempest/lib/cmd/check_uuid.py
+++ b/tempest/lib/cmd/check_uuid.py
@@ -173,9 +173,9 @@
@staticmethod
def _import_name(node):
- if type(node) == ast.Import:
+ if isinstance(node, ast.Import):
return node.names[0].name
- elif type(node) == ast.ImportFrom:
+ elif isinstance(node, ast.ImportFrom):
return '%s.%s' % (node.module, node.names[0].name)
def _add_import_for_test_uuid(self, patcher, src_parsed, source_path):
diff --git a/tempest/lib/cmd/skip_tracker.py b/tempest/lib/cmd/skip_tracker.py
index b5c9b95..b7d6a24 100755
--- a/tempest/lib/cmd/skip_tracker.py
+++ b/tempest/lib/cmd/skip_tracker.py
@@ -81,21 +81,23 @@
DEF_RE = re.compile(r'\s*def (\w+)\(')
bug_found = False
results = []
- lines = open(path, 'rb').readlines()
- for x, line in enumerate(lines):
- if not bug_found:
- res = BUG_RE.match(line)
- if res:
- bug_no = int(res.group(1))
- debug("Found bug skip %s on line %d", bug_no, x + 1)
- bug_found = True
- else:
- res = DEF_RE.match(line)
- if res:
- method = res.group(1)
- debug("Found test method %s skips for bug %d", method, bug_no)
- results.append((method, bug_no))
- bug_found = False
+ with open(path, 'rb') as content:
+ lines = content.readlines()
+ for x, line in enumerate(lines):
+ if not bug_found:
+ res = BUG_RE.match(line)
+ if res:
+ bug_no = int(res.group(1))
+ debug("Found bug skip %s on line %d", bug_no, x + 1)
+ bug_found = True
+ else:
+ res = DEF_RE.match(line)
+ if res:
+ method = res.group(1)
+ debug("Found test method %s skips for bug %d",
+ method, bug_no)
+ results.append((method, bug_no))
+ bug_found = False
return results
diff --git a/tempest/common/api_version_request.py b/tempest/lib/common/api_version_request.py
similarity index 92%
rename from tempest/common/api_version_request.py
rename to tempest/lib/common/api_version_request.py
index d8a5b56..b2b68a6 100644
--- a/tempest/common/api_version_request.py
+++ b/tempest/lib/common/api_version_request.py
@@ -14,7 +14,7 @@
import re
-from tempest import exceptions
+from tempest.lib import exceptions
# Define the minimum and maximum version of the API across all of the
@@ -39,6 +39,11 @@
This class provides convenience methods for manipulation
and comparison of version numbers that we need to do to
implement microversions.
+
+ :param version_string: String representation of APIVersionRequest.
+ Correct format is 'X.Y', where 'X' and 'Y' are int values.
+ None value should be used to create Null APIVersionRequest,
+ which is equal to 0.0
"""
# NOTE: This 'latest' version is a magic number, we assume any
@@ -47,13 +52,7 @@
latest_ver_minor = 99999
def __init__(self, version_string=None):
- """Create an API version request object.
-
- :param version_string: String representation of APIVersionRequest.
- Correct format is 'X.Y', where 'X' and 'Y' are int values.
- None value should be used to create Null APIVersionRequest,
- which is equal to 0.0
- """
+ """Create an API version request object."""
# NOTE(gmann): 'version_string' as String "None" will be considered as
# invalid version string.
self.ver_major = 0
@@ -77,6 +76,12 @@
return ("API Version Request: %s" % self.get_string())
def is_null(self):
+ """Checks whether version is null.
+
+ Return True if version object is null otherwise False.
+
+ :returns: boolean
+ """
return self.ver_major == 0 and self.ver_minor == 0
def _format_type_error(self, other):
@@ -120,9 +125,9 @@
greater than or equal to the minimum version and less than
or equal to the maximum version.
- @param min_version: Minimum acceptable version.
- @param max_version: Maximum acceptable version.
- @returns: boolean
+ :param min_version: Minimum acceptable version.
+ :param max_version: Maximum acceptable version.
+ :returns: boolean
If min_version is null then there is no minimum limit.
If max_version is null then there is no maximum limit.
diff --git a/tempest/common/api_version_utils.py b/tempest/lib/common/api_version_utils.py
similarity index 78%
rename from tempest/common/api_version_utils.py
rename to tempest/lib/common/api_version_utils.py
index 7c7e96a..73cd280 100644
--- a/tempest/common/api_version_utils.py
+++ b/tempest/lib/common/api_version_utils.py
@@ -14,8 +14,8 @@
import testtools
-from tempest.common import api_version_request
-from tempest import exceptions
+from tempest.lib.common import api_version_request
+from tempest.lib import exceptions
LATEST_MICROVERSION = 'latest'
@@ -35,6 +35,20 @@
def check_skip_with_microversion(test_min_version, test_max_version,
cfg_min_version, cfg_max_version):
+ """Checks API microversions range and returns whether test needs to be skip
+
+ Compare the test and configured microversion range and returns
+ whether test microversion range is out of configured one.
+ This method can be used to skip the test based on configured and test
+ microversion range.
+
+ :param test_min_version: Test Minimum Microversion
+ :param test_max_version: Test Maximum Microversion
+ :param cfg_min_version: Configured Minimum Microversion
+ :param cfg_max_version: Configured Maximum Microversion
+ :returns: boolean
+ """
+
min_version = api_version_request.APIVersionRequest(test_min_version)
max_version = api_version_request.APIVersionRequest(test_max_version)
config_min_version = api_version_request.APIVersionRequest(cfg_min_version)
@@ -68,6 +82,16 @@
def select_request_microversion(test_min_version, cfg_min_version):
+ """Select microversion from test and configuration.
+
+ Compare requested microversion and return the maximum
+ microversion out of those.
+
+ :param test_min_version: Test Minimum Microversion
+ :param cfg_min_version: Configured Minimum Microversion
+ :returns: Selected microversion string
+ """
+
test_version = api_version_request.APIVersionRequest(test_min_version)
cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
max_version = cfg_version if cfg_version >= test_version else test_version
@@ -82,10 +106,10 @@
Verify whether microversion is present in response header
and with specified 'api_microversion' value.
- @param: api_microversion_header_name: Microversion header name
+ :param api_microversion_header_name: Microversion header name
Example- "X-OpenStack-Nova-API-Version"
- @param: api_microversion: Microversion number like "2.10"
- @param: response_header: Response header where microversion is
+ :param api_microversion: Microversion number like "2.10"
+ :param response_header: Response header where microversion is
expected to be present.
"""
api_microversion_header_name = api_microversion_header_name.lower()
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 2bf7cdd..b9b2ae9 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -153,6 +153,20 @@
message = "Invalid structure of table with details"
+class InvalidAPIVersionString(TempestException):
+ message = ("API Version String %(version)s is of invalid format. Must "
+ "be of format MajorNum.MinorNum or string 'latest'.")
+
+
+class JSONSchemaNotFound(TempestException):
+ message = ("JSON Schema for %(version)s is not found in\n"
+ " %(schema_versions_info)s")
+
+
+class InvalidAPIVersionRange(TempestException):
+ message = ("The API version range is invalid.")
+
+
class BadAltAuth(TempestException):
"""Used when trying and failing to change to alt creds.
diff --git a/tempest/services/compute/json/base_compute_client.py b/tempest/lib/services/compute/base_compute_client.py
similarity index 78%
rename from tempest/services/compute/json/base_compute_client.py
rename to tempest/lib/services/compute/base_compute_client.py
index 8cfde4b..bbadc8f 100644
--- a/tempest/services/compute/json/base_compute_client.py
+++ b/tempest/lib/services/compute/base_compute_client.py
@@ -11,16 +11,30 @@
# 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.common import rest_client
-from tempest.common import api_version_request
-from tempest.common import api_version_utils
-from tempest import exceptions
+from tempest.lib.common import api_version_request
+from tempest.lib.common import api_version_utils
+from tempest.lib.common import rest_client
+from tempest.lib import exceptions
COMPUTE_MICROVERSION = None
class BaseComputeClient(rest_client.RestClient):
+ """Base compute service clients class to support microversion.
+
+ This class adds microversion to API request header if same is set
+ and provide interface to select appropriate JSON schema file for
+ response validation.
+
+ :param auth_provider: an auth provider object used to wrap requests in
+ auth
+ :param str service: The service name to use for the catalog lookup
+ :param str region: The region to use for the catalog lookup
+ request with microversion
+ :param kwargs: kwargs required by rest_client.RestClient
+ """
+
api_microversion_header_name = 'X-OpenStack-Nova-API-Version'
def __init__(self, auth_provider, service, region,
@@ -50,9 +64,10 @@
"""Get JSON schema
This method provides the matching schema for requested
- microversion (self.api_microversion).
+ microversion.
+
:param schema_versions_info: List of dict which provides schema
- information with range of valid versions.
+ information with range of valid versions.
Example -
schema_versions_info = [
{'min': None, 'max': '2.1', 'schema': schemav21},
diff --git a/tempest/lib/services/compute/versions_client.py b/tempest/lib/services/compute/versions_client.py
index 5898f93..ed82c74 100644
--- a/tempest/lib/services/compute/versions_client.py
+++ b/tempest/lib/services/compute/versions_client.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import re
+
from oslo_serialization import jsonutils as json
from six.moves import urllib
@@ -22,14 +24,17 @@
class VersionsClient(rest_client.RestClient):
def _get_base_version_url(self):
- # NOTE: The URL which is gotten from keystone's catalog contains
- # API version and project-id like "v2/{project-id}", but we need
- # to access the URL which doesn't contain them for getting API
- # versions. For that, here should use raw_request() instead of
- # get().
+ # NOTE: The URL which is got from keystone's catalog contains
+ # API version and project-id like "/app-name/v2/{project-id}" or
+ # "/v2/{project-id}", but we need to access the URL which doesn't
+ # contain API version for getting API versions. For that, here
+ # should use raw_request() instead of get().
endpoint = self.base_url
- url = urllib.parse.urlparse(endpoint)
- return '%s://%s/' % (url.scheme, url.netloc)
+ url = urllib.parse.urlsplit(endpoint)
+ new_path = re.split(r'(^|/)+v\d+(\.\d+)?', url.path)[0]
+ url = list(url)
+ url[2] = new_path + '/'
+ return urllib.parse.urlunsplit(url)
def list_versions(self):
version_url = self._get_base_version_url()
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index e4a4d92..8ba5f9a 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -66,6 +66,7 @@
cls.network_client = cls.manager.network_client
cls.networks_client = cls.manager.networks_client
cls.ports_client = cls.manager.ports_client
+ cls.routers_client = cls.manager.routers_client
cls.subnets_client = cls.manager.subnets_client
cls.floating_ips_client = cls.manager.floating_ips_client
cls.security_groups_client = cls.manager.security_groups_client
@@ -386,8 +387,6 @@
if properties is None:
properties = {}
name = data_utils.rand_name('%s-' % name)
- image_file = open(path, 'rb')
- self.addCleanup(image_file.close)
params = {
'name': name,
'container_format': fmt,
@@ -398,7 +397,8 @@
image = self.image_client.create_image(**params)['image']
self.addCleanup(self.image_client.delete_image, image['id'])
self.assertEqual("queued", image['status'])
- self.image_client.update_image(image['id'], data=image_file)
+ with open(path, 'rb') as image_file:
+ self.image_client.update_image(image['id'], data=image_file)
return image['id']
def glance_image_create(self):
@@ -683,17 +683,21 @@
cls.tenant_id = cls.manager.identity_client.tenant_id
def _create_network(self, client=None, networks_client=None,
- tenant_id=None, namestart='network-smoke-'):
+ routers_client=None, tenant_id=None,
+ namestart='network-smoke-'):
if not client:
client = self.network_client
if not networks_client:
networks_client = self.networks_client
+ if not routers_client:
+ routers_client = self.routers_client
if not tenant_id:
tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
result = networks_client.create_network(name=name, tenant_id=tenant_id)
network = net_resources.DeletableNetwork(
- networks_client=networks_client, **result['network'])
+ networks_client=networks_client, routers_client=routers_client,
+ **result['network'])
self.assertEqual(network.name, name)
self.addCleanup(self.delete_wrapper, network.delete)
return network
@@ -712,7 +716,7 @@
def _list_routers(self, *args, **kwargs):
"""List routers using admin creds """
- routers_list = self.admin_manager.network_client.list_routers(
+ routers_list = self.admin_manager.routers_client.list_routers(
*args, **kwargs)
return routers_list['routers']
@@ -729,7 +733,8 @@
return agents_list['agents']
def _create_subnet(self, network, client=None, subnets_client=None,
- namestart='subnet-smoke', **kwargs):
+ routers_client=None, namestart='subnet-smoke',
+ **kwargs):
"""Create a subnet for the given network
within the cidr block configured for tenant networks.
@@ -738,6 +743,8 @@
client = self.network_client
if not subnets_client:
subnets_client = self.subnets_client
+ if not routers_client:
+ routers_client = self.routers_client
def cidr_in_use(cidr, tenant_id):
"""Check cidr existence
@@ -785,7 +792,7 @@
self.assertIsNotNone(result, 'Unable to allocate tenant network')
subnet = net_resources.DeletableSubnet(
network_client=client, subnets_client=subnets_client,
- **result['subnet'])
+ routers_client=routers_client, **result['subnet'])
self.assertEqual(subnet.cidr, str_cidr)
self.addCleanup(self.delete_wrapper, subnet.delete)
return subnet
@@ -985,7 +992,7 @@
sg_dict['tenant_id'] = tenant_id
result = client.create_security_group(**sg_dict)
secgroup = net_resources.DeletableSecurityGroup(
- client=client,
+ client=client, routers_client=self.routers_client,
**result['security_group']
)
self.assertEqual(secgroup.name, sg_name)
@@ -1121,7 +1128,7 @@
routes traffic to the public network.
"""
if not client:
- client = self.network_client
+ client = self.routers_client
if not tenant_id:
tenant_id = client.tenant_id
router_id = CONF.network.public_router_id
@@ -1140,14 +1147,14 @@
def _create_router(self, client=None, tenant_id=None,
namestart='router-smoke'):
if not client:
- client = self.network_client
+ client = self.routers_client
if not tenant_id:
tenant_id = client.tenant_id
name = data_utils.rand_name(namestart)
result = client.create_router(name=name,
admin_state_up=True,
tenant_id=tenant_id)
- router = net_resources.DeletableRouter(client=client,
+ router = net_resources.DeletableRouter(routers_client=client,
**result['router'])
self.assertEqual(router.name, name)
self.addCleanup(self.delete_wrapper, router.delete)
@@ -1158,8 +1165,8 @@
self.assertEqual(admin_state_up, router.admin_state_up)
def create_networks(self, client=None, networks_client=None,
- subnets_client=None, tenant_id=None,
- dns_nameservers=None):
+ routers_client=None, subnets_client=None,
+ tenant_id=None, dns_nameservers=None):
"""Create a network with a subnet connected to a router.
The baremetal driver is a special case since all nodes are
@@ -1187,10 +1194,12 @@
network = self._create_network(
client=client, networks_client=networks_client,
tenant_id=tenant_id)
- router = self._get_router(client=client, tenant_id=tenant_id)
+ router = self._get_router(client=routers_client,
+ tenant_id=tenant_id)
subnet_kwargs = dict(network=network, client=client,
- subnets_client=subnets_client)
+ subnets_client=subnets_client,
+ routers_client=routers_client)
# use explicit check because empty list is a valid option
if dns_nameservers is not None:
subnet_kwargs['dns_nameservers'] = dns_nameservers
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
deleted file mode 100644
index 9ed831c..0000000
--- a/tempest/scenario/test_large_ops.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2013 NEC Corporation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.common import fixed_network
-from tempest.common.utils import data_utils
-from tempest.common import waiters
-from tempest import config
-from tempest.lib import exceptions as lib_exc
-from tempest.scenario import manager
-from tempest import test
-
-CONF = config.CONF
-
-
-class TestLargeOpsScenario(manager.ScenarioTest):
-
- """Test large operations.
-
- This test below:
- * Spin up multiple instances in one nova call, and repeat three times
- * as a regular user
- * TODO: same thing for cinder
-
- """
-
- @classmethod
- def skip_checks(cls):
- super(TestLargeOpsScenario, cls).skip_checks()
- if CONF.scenario.large_ops_number < 1:
- raise cls.skipException("large_ops_number not set to multiple "
- "instances")
-
- @classmethod
- def setup_credentials(cls):
- cls.set_network_resources()
- super(TestLargeOpsScenario, cls).setup_credentials()
-
- @classmethod
- def resource_setup(cls):
- super(TestLargeOpsScenario, cls).resource_setup()
- # list of cleanup calls to be executed in reverse order
- cls._cleanup_resources = []
-
- @classmethod
- def resource_cleanup(cls):
- while cls._cleanup_resources:
- function, args, kwargs = cls._cleanup_resources.pop(-1)
- try:
- function(*args, **kwargs)
- except lib_exc.NotFound:
- pass
- super(TestLargeOpsScenario, cls).resource_cleanup()
-
- @classmethod
- def addCleanupClass(cls, function, *arguments, **keywordArguments):
- cls._cleanup_resources.append((function, arguments, keywordArguments))
-
- def _wait_for_server_status(self, status):
- for server in self.servers:
- # Make sure nova list keeps working throughout the build process
- self.servers_client.list_servers()
- waiters.wait_for_server_status(self.servers_client,
- server['id'], status)
-
- def nova_boot(self, image):
- name = data_utils.rand_name('scenario-server')
- flavor_id = CONF.compute.flavor_ref
- # Explicitly create secgroup to avoid cleanup at the end of testcases.
- # Since no traffic is tested, we don't need to actually add rules to
- # secgroup
- secgroup = self.compute_security_groups_client.create_security_group(
- name='secgroup-%s' % name,
- description='secgroup-desc-%s' % name)['security_group']
- self.addCleanupClass(
- self.compute_security_groups_client.delete_security_group,
- secgroup['id'])
- create_kwargs = {
- 'min_count': CONF.scenario.large_ops_number,
- 'security_groups': [{'name': secgroup['name']}]
- }
- network = self.get_tenant_network()
- create_kwargs = fixed_network.set_networks_kwarg(network,
- create_kwargs)
- self.servers_client.create_server(
- name=name,
- imageRef=image,
- flavorRef=flavor_id,
- **create_kwargs)
- # needed because of bug 1199788
- params = {'name': name}
- 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
- # before cleanup continues
- self.addCleanupClass(waiters.wait_for_server_termination,
- self.servers_client,
- server['id'])
- for server in self.servers:
- self.addCleanupClass(self.servers_client.delete_server,
- server['id'])
- self._wait_for_server_status('ACTIVE')
-
- def _large_ops_scenario(self):
- image = self.glance_image_create()
- self.nova_boot(image)
-
- @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_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 4d03ed7..9e2477e 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -680,7 +680,7 @@
# TODO(yfried): refactor this test to be used for other agents (dhcp)
# as well
- list_hosts = (self.admin_manager.network_client.
+ list_hosts = (self.admin_manager.routers_client.
list_l3_agents_hosting_router)
schedule_router = (self.admin_manager.network_agents_client.
create_router_on_l3_agent)
@@ -693,7 +693,7 @@
# NOTE(kevinbenton): we have to use the admin credentials to check
# for the distributed flag because self.router only has a tenant view.
- admin = self.admin_manager.network_client.show_router(self.router.id)
+ admin = self.admin_manager.routers_client.show_router(self.router.id)
if admin['router'].get('distributed', False):
msg = "Rescheduling test does not apply to distributed routers."
raise self.skipException(msg)
@@ -776,7 +776,7 @@
private_key = self._get_server_key(server)
ssh_client = self.get_remote_client(fip.floating_ip_address,
private_key=private_key)
- spoof_nic = ssh_client.get_nic_name(spoof_port["mac_address"])
+ spoof_nic = ssh_client.get_nic_name_by_mac(spoof_port["mac_address"])
dhcp_ports = self._list_ports(device_owner="network:dhcp",
network_id=self.new_net["id"])
new_net_dhcp = dhcp_ports[0]["fixed_ips"][0]["ip_address"]
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index fc33dd9..66c8ade 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -145,7 +145,7 @@
"ports: %s")
% (self.network_v6, ports))
mac6 = ports[0]
- ssh.set_nic_state(ssh.get_nic_name(mac6))
+ ssh.set_nic_state(ssh.get_nic_name_by_mac(mac6))
def _prepare_and_test(self, address6_mode, n_subnets6=1, dualnet=False):
net_list = self.prepare_network(address6_mode=address6_mode,
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 18bd764..058f43b 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.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.
+from oslo_log import log
from tempest import clients
from tempest.common.utils import data_utils
@@ -20,6 +21,7 @@
from tempest import test
CONF = config.CONF
+LOG = log.getLogger(__name__)
class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest):
@@ -151,6 +153,14 @@
@classmethod
def resource_setup(cls):
super(TestSecurityGroupsBasicOps, cls).resource_setup()
+
+ cls.multi_node = CONF.compute.min_compute_nodes > 1 and \
+ test.is_scheduler_filter_enabled("DifferentHostFilter")
+ if cls.multi_node:
+ LOG.info("Working in Multi Node mode")
+ else:
+ LOG.info("Working in Single Node mode")
+
cls.floating_ips = {}
cls.tenants = {}
creds = cls.manager.credentials
@@ -162,6 +172,12 @@
cls.floating_ip_access = not CONF.network.public_router_id
def setUp(self):
+ """Set up a single tenant with an accessible server.
+
+ If multi-host is enabled, save created server uuids.
+ """
+ self.servers = []
+
super(TestSecurityGroupsBasicOps, self).setUp()
self._deploy_tenant(self.primary_tenant)
self._verify_network_details(self.primary_tenant)
@@ -233,21 +249,44 @@
# and distributed routers; 'device_owner' is "" by default.
return port['device_owner'].startswith('network:router_interface')
- def _create_server(self, name, tenant, security_groups=None):
- """creates a server and assigns to security group"""
+ def _create_server(self, name, tenant, security_groups=None, **kwargs):
+ """Creates a server and assigns it to security group.
+
+ If multi-host is enabled, Ensures servers are created on different
+ compute nodes, by storing created servers' ids and uses different_host
+ as scheduler_hints on creation.
+ Validates servers are created as requested, using admin client.
+ """
if security_groups is None:
security_groups = [tenant.security_groups['default']]
security_groups_names = [{'name': s['name']} for s in security_groups]
+ if self.multi_node:
+ kwargs["scheduler_hints"] = {'different_host': self.servers}
server = self.create_server(
name=name,
networks=[{'uuid': tenant.network.id}],
key_name=tenant.keypair['name'],
security_groups=security_groups_names,
wait_until='ACTIVE',
- clients=tenant.manager)
+ clients=tenant.manager,
+ **kwargs)
self.assertEqual(
sorted([s['name'] for s in security_groups]),
sorted([s['name'] for s in server['security_groups']]))
+
+ # Verify servers are on different compute nodes
+ if self.multi_node:
+ adm_get_server = self.admin_manager.servers_client.show_server
+ new_host = adm_get_server(server["id"])["server"][
+ "OS-EXT-SRV-ATTR:host"]
+ host_list = [adm_get_server(s)["server"]["OS-EXT-SRV-ATTR:host"]
+ for s in self.servers]
+ self.assertNotIn(new_host, host_list,
+ message="Failed to boot servers on different "
+ "Compute nodes.")
+
+ self.servers.append(server["id"])
+
return server
def _create_tenant_servers(self, tenant, num=1):
@@ -284,6 +323,7 @@
network, subnet, router = self.create_networks(
client=tenant.manager.network_client,
networks_client=tenant.manager.networks_client,
+ routers_client=tenant.manager.routers_client,
subnets_client=tenant.manager.subnets_client)
tenant.set_network(network, subnet, router)
@@ -348,6 +388,7 @@
)
self._create_security_group_rule(
secgroup=tenant.security_groups['default'],
+ security_groups_client=tenant.manager.security_groups_client,
**ruleset
)
access_point_ssh = self._connect_to_access_point(tenant)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 4ce57db..71bb50e 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_log import log as logging
+
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
@@ -17,6 +19,7 @@
from tempest import test
CONF = config.CONF
+LOG = logging.getLogger(__name__)
class TestVolumeBootPattern(manager.ScenarioTest):
@@ -32,6 +35,11 @@
* Boot an additional instance from the new snapshot based volume
* Check written content in the instance booted from snapshot
"""
+
+ # Boot from volume scenario is quite slow, and needs extra
+ # breathing room to get through deletes in the time allotted.
+ TIMEOUT_SCALING_FACTOR = 2
+
@classmethod
def skip_checks(cls):
super(TestVolumeBootPattern, cls).skip_checks()
@@ -101,42 +109,53 @@
@test.attr(type='smoke')
@test.services('compute', 'volume', 'image')
def test_volume_boot_pattern(self):
+ LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
security_group = self._create_security_group()
# create an instance from volume
+ LOG.info("Booting instance 1 from volume")
volume_origin = self._create_volume_from_image()
instance_1st = self._boot_instance_from_volume(volume_origin['id'],
keypair, security_group)
+ LOG.info("Booted first instance: %s" % instance_1st)
# write content to volume on instance
+ LOG.info("Setting timestamp in instance %s" % instance_1st)
ip_instance_1st = self.get_server_ip(instance_1st)
timestamp = self.create_timestamp(ip_instance_1st,
private_key=keypair['private_key'])
# delete instance
+ LOG.info("Deleting first instance: %s" % instance_1st)
self._delete_server(instance_1st)
# create a 2nd instance from volume
instance_2nd = self._boot_instance_from_volume(volume_origin['id'],
keypair, security_group)
+ LOG.info("Booted second instance %s" % instance_2nd)
# check the content of written file
+ LOG.info("Getting timestamp in instance %s" % instance_2nd)
ip_instance_2nd = self.get_server_ip(instance_2nd)
timestamp2 = self.get_timestamp(ip_instance_2nd,
private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp2)
# snapshot a volume
+ LOG.info("Creating snapshot from volume: %s" % volume_origin['id'])
snapshot = self._create_snapshot_from_volume(volume_origin['id'])
# create a 3rd instance from snapshot
+ LOG.info("Creating third instance from snapshot: %s" % snapshot['id'])
volume = self._create_volume_from_snapshot(snapshot['id'])
server_from_snapshot = (
self._boot_instance_from_volume(volume['id'],
keypair, security_group))
# check the content of written file
+ LOG.info("Logging into third instance to get timestamp: %s" %
+ server_from_snapshot)
server_from_snapshot_ip = self.get_server_ip(server_from_snapshot)
timestamp3 = self.get_timestamp(server_from_snapshot_ip,
private_key=keypair['private_key'])
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index d8cb99d..6e24801 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -16,7 +16,7 @@
import six
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
def handle_errors(f):
@@ -39,7 +39,7 @@
return wrapper
-class BaremetalClient(service_client.ServiceClient):
+class BaremetalClient(rest_client.RestClient):
"""Base Tempest REST client for Ironic API."""
uri_prefix = ''
diff --git a/tempest/services/compute/json/keypairs_client.py b/tempest/services/compute/json/keypairs_client.py
index ec9b1e0..2af55b2 100644
--- a/tempest/services/compute/json/keypairs_client.py
+++ b/tempest/services/compute/json/keypairs_client.py
@@ -17,8 +17,8 @@
from tempest.api_schema.response.compute.v2_1 import keypairs as schemav21
from tempest.api_schema.response.compute.v2_2 import keypairs as schemav22
-from tempest.common import service_client
-from tempest.services.compute.json import base_compute_client
+from tempest.lib.common import rest_client
+from tempest.lib.services.compute import base_compute_client
class KeyPairsClient(base_compute_client.BaseComputeClient):
@@ -31,14 +31,14 @@
body = json.loads(body)
schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.list_keypairs, resp, body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_keypair(self, keypair_name):
resp, body = self.get("os-keypairs/%s" % keypair_name)
body = json.loads(body)
schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.get_keypair, resp, body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_keypair(self, **kwargs):
post_body = json.dumps({'keypair': kwargs})
@@ -46,10 +46,10 @@
body = json.loads(body)
schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.create_keypair, resp, body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_keypair(self, keypair_name):
resp, body = self.delete("os-keypairs/%s" % keypair_name)
schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.delete_keypair, resp, body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/data_processing/v1_1/data_processing_client.py b/tempest/services/data_processing/v1_1/data_processing_client.py
index 5aa2622..c74672f 100644
--- a/tempest/services/data_processing/v1_1/data_processing_client.py
+++ b/tempest/services/data_processing/v1_1/data_processing_client.py
@@ -14,10 +14,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class DataProcessingClient(service_client.ServiceClient):
+class DataProcessingClient(rest_client.RestClient):
def _request_and_check_resp(self, request_func, uri, resp_status):
"""Make a request and check response status code.
@@ -26,7 +26,7 @@
"""
resp, body = request_func(uri)
self.expected_success(resp_status, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def _request_and_check_resp_data(self, request_func, uri, resp_status):
"""Make a request and check response status code.
@@ -47,7 +47,7 @@
resp, body = request_func(uri, headers=headers, *args, **kwargs)
self.expected_success(resp_status, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_node_group_templates(self):
"""List all node group templates for a user."""
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
index dbb5172..bd8ffb0 100644
--- a/tempest/services/database/json/flavors_client.py
+++ b/tempest/services/database/json/flavors_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves import urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class DatabaseFlavorsClient(service_client.ServiceClient):
+class DatabaseFlavorsClient(rest_client.RestClient):
def list_db_flavors(self, params=None):
url = 'flavors'
@@ -29,10 +29,10 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_db_flavor(self, db_flavor_id):
resp, body = self.get("flavors/%s" % db_flavor_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/database/json/limits_client.py b/tempest/services/database/json/limits_client.py
index da495d7..a1c58c2 100644
--- a/tempest/services/database/json/limits_client.py
+++ b/tempest/services/database/json/limits_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class DatabaseLimitsClient(service_client.ServiceClient):
+class DatabaseLimitsClient(rest_client.RestClient):
def list_db_limits(self, params=None):
"""List all limits."""
@@ -29,4 +29,4 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/database/json/versions_client.py b/tempest/services/database/json/versions_client.py
index 7a560d9..2f28203 100644
--- a/tempest/services/database/json/versions_client.py
+++ b/tempest/services/database/json/versions_client.py
@@ -16,24 +16,14 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class DatabaseVersionsClient(service_client.ServiceClient):
+class DatabaseVersionsClient(rest_client.RestClient):
- def __init__(self, auth_provider, service, region,
- endpoint_type=None, build_interval=None, build_timeout=None,
- disable_ssl_certificate_validation=None, ca_certs=None,
- trace_requests=None):
- dscv = disable_ssl_certificate_validation
+ def __init__(self, auth_provider, service, region, **kwargs):
super(DatabaseVersionsClient, self).__init__(
- auth_provider, service, region,
- endpoint_type=endpoint_type,
- build_interval=build_interval,
- build_timeout=build_timeout,
- disable_ssl_certificate_validation=dscv,
- ca_certs=ca_certs,
- trace_requests=trace_requests)
+ auth_provider, service, region, **kwargs)
self.skip_path()
def list_db_versions(self, params=None):
@@ -45,4 +35,4 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/endpoints_client.py b/tempest/services/identity/v2/json/endpoints_client.py
index ff9907d..ba9f867 100644
--- a/tempest/services/identity/v2/json/endpoints_client.py
+++ b/tempest/services/identity/v2/json/endpoints_client.py
@@ -14,10 +14,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class EndpointsClient(service_client.ServiceClient):
+class EndpointsClient(rest_client.RestClient):
api_version = "v2.0"
def create_endpoint(self, service_id, region_id, **kwargs):
@@ -33,18 +33,18 @@
resp, body = self.post('/endpoints', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_endpoints(self):
"""List Endpoints - Returns Endpoints."""
resp, body = self.get('/endpoints')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_endpoint(self, endpoint_id):
"""Delete an endpoint."""
url = '/endpoints/%s' % endpoint_id
resp, body = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index f045bb7..6caff0e 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -12,10 +12,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class IdentityClient(service_client.ServiceClient):
+class IdentityClient(rest_client.RestClient):
api_version = "v2.0"
def show_api_description(self):
@@ -24,24 +24,24 @@
resp, body = self.get(url)
self.expected_success([200, 203], resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_token(self, token_id):
"""Get token details."""
resp, body = self.get("tokens/%s" % token_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_token(self, token_id):
"""Delete a token."""
resp, body = self.delete("tokens/%s" % token_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_extensions(self):
"""List all the extensions."""
resp, body = self.get('/extensions')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/roles_client.py b/tempest/services/identity/v2/json/roles_client.py
index ef6dfe9..acd97c6 100644
--- a/tempest/services/identity/v2/json/roles_client.py
+++ b/tempest/services/identity/v2/json/roles_client.py
@@ -12,10 +12,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class RolesClient(service_client.ServiceClient):
+class RolesClient(rest_client.RestClient):
api_version = "v2.0"
def create_role(self, **kwargs):
@@ -28,14 +28,14 @@
resp, body = self.post('OS-KSADM/roles', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_role(self, role_id):
"""Get a role by its id."""
resp, body = self.get('OS-KSADM/roles/%s' % role_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_role(self, role_id):
"""Delete a role."""
@@ -49,7 +49,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def assign_user_role(self, tenant_id, user_id, role_id):
"""Add roles to a user on a tenant."""
@@ -57,18 +57,18 @@
(tenant_id, user_id, role_id), "")
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_user_role(self, tenant_id, user_id, role_id):
"""Removes a role assignment for a user on a tenant."""
resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_roles(self):
"""Returns roles."""
resp, body = self.get('OS-KSADM/roles')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/services_client.py b/tempest/services/identity/v2/json/services_client.py
index 436d00d..d8be6c6 100644
--- a/tempest/services/identity/v2/json/services_client.py
+++ b/tempest/services/identity/v2/json/services_client.py
@@ -14,10 +14,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class ServicesClient(service_client.ServiceClient):
+class ServicesClient(rest_client.RestClient):
api_version = "v2.0"
def create_service(self, name, type, **kwargs):
@@ -31,7 +31,7 @@
resp, body = self.post('/OS-KSADM/services', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_service(self, service_id):
"""Get Service."""
@@ -39,18 +39,18 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_services(self):
"""List Service - Returns Services."""
resp, body = self.get('/OS-KSADM/services')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_service(self, service_id):
"""Delete Service."""
url = '/OS-KSADM/services/%s' % service_id
resp, body = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/tenants_client.py b/tempest/services/identity/v2/json/tenants_client.py
index 937ae6f..034938e 100644
--- a/tempest/services/identity/v2/json/tenants_client.py
+++ b/tempest/services/identity/v2/json/tenants_client.py
@@ -14,10 +14,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class TenantsClient(service_client.ServiceClient):
+class TenantsClient(rest_client.RestClient):
api_version = "v2.0"
def create_tenant(self, name, **kwargs):
@@ -36,27 +36,27 @@
resp, body = self.post('tenants', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_tenant(self, tenant_id):
"""Delete a tenant."""
resp, body = self.delete('tenants/%s' % str(tenant_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_tenant(self, tenant_id):
"""Get tenant details."""
resp, body = self.get('tenants/%s' % str(tenant_id))
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_tenants(self):
"""Returns tenants."""
resp, body = self.get('tenants')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant."""
@@ -74,11 +74,11 @@
resp, body = self.post('tenants/%s' % tenant_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_tenant_users(self, tenant_id):
"""List users for a Tenant."""
resp, body = self.get('/tenants/%s/users' % tenant_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v2/json/users_client.py b/tempest/services/identity/v2/json/users_client.py
index 5327638..5f8127f 100644
--- a/tempest/services/identity/v2/json/users_client.py
+++ b/tempest/services/identity/v2/json/users_client.py
@@ -12,10 +12,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class UsersClient(service_client.ServiceClient):
+class UsersClient(rest_client.RestClient):
api_version = "v2.0"
def create_user(self, name, password, tenant_id, email, **kwargs):
@@ -33,7 +33,7 @@
resp, body = self.post('users', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_user(self, user_id, **kwargs):
"""Updates a user."""
@@ -41,27 +41,27 @@
resp, body = self.put('users/%s' % user_id, put_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_user(self, user_id):
"""Delete a user."""
resp, body = self.delete("users/%s" % user_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_users(self):
"""Get the list of users."""
resp, body = self.get("users")
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def enable_disable_user(self, user_id, **kwargs):
"""Enables or disables a user.
@@ -77,7 +77,7 @@
resp, body = self.put('users/%s/enabled' % user_id, put_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_user_password(self, user_id, **kwargs):
"""Update User Password."""
@@ -89,7 +89,7 @@
resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_user_own_password(self, user_id, **kwargs):
"""User updates own password"""
@@ -104,7 +104,7 @@
resp, body = self.patch('OS-KSCRUD/users/%s' % user_id, patch_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_user_ec2_credentials(self, user_id, **kwargs):
# TODO(piyush): Current api-site doesn't contain this API description.
@@ -115,23 +115,23 @@
post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_user_ec2_credentials(self, user_id, access):
resp, body = self.delete('/users/%s/credentials/OS-EC2/%s' %
(user_id, access))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_user_ec2_credentials(self, user_id):
resp, body = self.get('/users/%s/credentials/OS-EC2' % user_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_user_ec2_credentials(self, user_id, access):
resp, body = self.get('/users/%s/credentials/OS-EC2/%s' %
(user_id, access))
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/credentials_client.py b/tempest/services/identity/v3/json/credentials_client.py
index 753e960..6ab94d0 100644
--- a/tempest/services/identity/v3/json/credentials_client.py
+++ b/tempest/services/identity/v3/json/credentials_client.py
@@ -19,10 +19,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class CredentialsClient(service_client.ServiceClient):
+class CredentialsClient(rest_client.RestClient):
api_version = "v3"
def create_credential(self, **kwargs):
@@ -36,7 +36,7 @@
self.expected_success(201, resp.status)
body = json.loads(body)
body['credential']['blob'] = json.loads(body['credential']['blob'])
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_credential(self, credential_id, **kwargs):
"""Updates a credential.
@@ -49,7 +49,7 @@
self.expected_success(200, resp.status)
body = json.loads(body)
body['credential']['blob'] = json.loads(body['credential']['blob'])
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_credential(self, credential_id):
"""To GET Details of a credential."""
@@ -57,17 +57,17 @@
self.expected_success(200, resp.status)
body = json.loads(body)
body['credential']['blob'] = json.loads(body['credential']['blob'])
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_credentials(self):
"""Lists out all the available credentials."""
resp, body = self.get('credentials')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_credential(self, credential_id):
"""Deletes a credential."""
resp, body = self.delete('credentials/%s' % credential_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/domains_client.py b/tempest/services/identity/v3/json/domains_client.py
index 626a474..d129a0a 100644
--- a/tempest/services/identity/v3/json/domains_client.py
+++ b/tempest/services/identity/v3/json/domains_client.py
@@ -15,10 +15,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class DomainsClient(service_client.ServiceClient):
+class DomainsClient(rest_client.RestClient):
api_version = "v3"
def create_domain(self, name, **kwargs):
@@ -34,13 +34,13 @@
resp, body = self.post('domains', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_domain(self, domain_id):
"""Deletes a domain."""
resp, body = self.delete('domains/%s' % str(domain_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_domains(self, params=None):
"""List Domains."""
@@ -50,7 +50,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_domain(self, domain_id, **kwargs):
"""Updates a domain."""
@@ -67,11 +67,11 @@
resp, body = self.patch('domains/%s' % domain_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_domain(self, domain_id):
"""Get Domain details."""
resp, body = self.get('domains/%s' % domain_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/services/identity/v3/json/endpoints_client.py
index 8ab7464..db30508 100644
--- a/tempest/services/identity/v3/json/endpoints_client.py
+++ b/tempest/services/identity/v3/json/endpoints_client.py
@@ -19,10 +19,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class EndPointClient(service_client.ServiceClient):
+class EndPointsClient(rest_client.RestClient):
api_version = "v3"
def list_endpoints(self):
@@ -30,7 +30,7 @@
resp, body = self.get('endpoints')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_endpoint(self, **kwargs):
"""Create endpoint.
@@ -42,7 +42,7 @@
resp, body = self.post('endpoints', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_endpoint(self, endpoint_id, **kwargs):
"""Updates an endpoint with given parameters.
@@ -54,17 +54,17 @@
resp, body = self.patch('endpoints/%s' % endpoint_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_endpoint(self, endpoint_id):
"""Delete endpoint."""
resp_header, resp_body = self.delete('endpoints/%s' % endpoint_id)
self.expected_success(204, resp_header.status)
- return service_client.ResponseBody(resp_header, resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
def show_endpoint(self, endpoint_id):
"""Get endpoint."""
resp_header, resp_body = self.get('endpoints/%s' % endpoint_id)
self.expected_success(200, resp_header.status)
resp_body = json.loads(resp_body)
- return service_client.ResponseBody(resp_header, resp_body)
+ return rest_client.ResponseBody(resp_header, resp_body)
diff --git a/tempest/services/identity/v3/json/groups_client.py b/tempest/services/identity/v3/json/groups_client.py
index 6ed85cf..1a495f8 100644
--- a/tempest/services/identity/v3/json/groups_client.py
+++ b/tempest/services/identity/v3/json/groups_client.py
@@ -19,10 +19,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class GroupsClient(service_client.ServiceClient):
+class GroupsClient(rest_client.RestClient):
api_version = "v3"
def create_group(self, **kwargs):
@@ -35,21 +35,21 @@
resp, body = self.post('groups', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_group(self, group_id):
"""Get group details."""
resp, body = self.get('groups/%s' % group_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_groups(self):
"""Lists the groups."""
resp, body = self.get('groups')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_group(self, group_id, **kwargs):
"""Updates a group.
@@ -61,36 +61,36 @@
resp, body = self.patch('groups/%s' % group_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_group(self, group_id):
"""Delete a group."""
resp, body = self.delete('groups/%s' % str(group_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def add_group_user(self, group_id, user_id):
"""Add user into group."""
resp, body = self.put('groups/%s/users/%s' % (group_id, user_id),
None)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_group_users(self, group_id):
"""List users in group."""
resp, body = self.get('groups/%s/users' % group_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_group_user(self, group_id, user_id):
"""Delete user in group."""
resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def check_group_user_existence(self, group_id, user_id):
"""Check user in group."""
resp, body = self.head('groups/%s/users/%s' % (group_id, user_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index e4daf7a..8177e35 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -15,10 +15,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class IdentityV3Client(service_client.ServiceClient):
+class IdentityClient(rest_client.RestClient):
api_version = "v3"
def show_api_description(self):
@@ -27,51 +27,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def create_role(self, **kwargs):
- """Create a Role.
-
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#createRole
- """
- post_body = json.dumps({'role': kwargs})
- resp, body = self.post('roles', post_body)
- self.expected_success(201, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def show_role(self, role_id):
- """GET a Role."""
- resp, body = self.get('roles/%s' % str(role_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def list_roles(self):
- """Get the list of Roles."""
- resp, body = self.get("roles")
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def update_role(self, role_id, **kwargs):
- """Update a Role.
-
- Available params: see http://developer.openstack.org/
- api-ref-identity-v3.html#updateRole
- """
- post_body = json.dumps({'role': kwargs})
- resp, body = self.patch('roles/%s' % str(role_id), post_body)
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def delete_role(self, role_id):
- """Delete a role."""
- resp, body = self.delete('roles/%s' % str(role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_token(self, resp_token):
"""Get token details."""
@@ -79,131 +35,11 @@
resp, body = self.get("auth/tokens", headers=headers)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_token(self, resp_token):
"""Deletes token."""
headers = {'X-Subject-Token': resp_token}
resp, body = self.delete("auth/tokens", headers=headers)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def assign_user_role_on_project(self, project_id, user_id, role_id):
- """Add roles to a user on a project."""
- resp, body = self.put('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def assign_user_role_on_domain(self, domain_id, user_id, role_id):
- """Add roles to a user on a domain."""
- resp, body = self.put('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id), None)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def list_user_roles_on_project(self, project_id, user_id):
- """list roles of a user on a project."""
- resp, body = self.get('projects/%s/users/%s/roles' %
- (project_id, user_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def list_user_roles_on_domain(self, domain_id, user_id):
- """list roles of a user on a domain."""
- resp, body = self.get('domains/%s/users/%s/roles' %
- (domain_id, user_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def delete_role_from_user_on_project(self, project_id, user_id, role_id):
- """Delete role of a user on a project."""
- resp, body = self.delete('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def delete_role_from_user_on_domain(self, domain_id, user_id, role_id):
- """Delete role of a user on a domain."""
- resp, body = self.delete('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def check_user_role_existence_on_project(self, project_id,
- user_id, role_id):
- """Check role of a user on a project."""
- resp, body = self.head('projects/%s/users/%s/roles/%s' %
- (project_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
-
- def check_user_role_existence_on_domain(self, domain_id,
- user_id, role_id):
- """Check role of a user on a domain."""
- resp, body = self.head('domains/%s/users/%s/roles/%s' %
- (domain_id, user_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
-
- def assign_group_role_on_project(self, project_id, group_id, role_id):
- """Add roles to a user on a project."""
- resp, body = self.put('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def assign_group_role_on_domain(self, domain_id, group_id, role_id):
- """Add roles to a user on a domain."""
- resp, body = self.put('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id), None)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def list_group_roles_on_project(self, project_id, group_id):
- """list roles of a user on a project."""
- resp, body = self.get('projects/%s/groups/%s/roles' %
- (project_id, group_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def list_group_roles_on_domain(self, domain_id, group_id):
- """list roles of a user on a domain."""
- resp, body = self.get('domains/%s/groups/%s/roles' %
- (domain_id, group_id))
- self.expected_success(200, resp.status)
- body = json.loads(body)
- return service_client.ResponseBody(resp, body)
-
- def delete_role_from_group_on_project(self, project_id, group_id, role_id):
- """Delete role of a user on a project."""
- resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def delete_role_from_group_on_domain(self, domain_id, group_id, role_id):
- """Delete role of a user on a domain."""
- resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def check_role_from_group_on_project_existence(self, project_id,
- group_id, role_id):
- """Check role of a user on a project."""
- resp, body = self.head('projects/%s/groups/%s/roles/%s' %
- (project_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
-
- def check_role_from_group_on_domain_existence(self, domain_id,
- group_id, role_id):
- """Check role of a user on a domain."""
- resp, body = self.head('domains/%s/groups/%s/roles/%s' %
- (domain_id, group_id, role_id))
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/policies_client.py b/tempest/services/identity/v3/json/policies_client.py
index 639ed6d..f28db9a 100644
--- a/tempest/services/identity/v3/json/policies_client.py
+++ b/tempest/services/identity/v3/json/policies_client.py
@@ -19,10 +19,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class PoliciesClient(service_client.ServiceClient):
+class PoliciesClient(rest_client.RestClient):
api_version = "v3"
def create_policy(self, **kwargs):
@@ -35,14 +35,14 @@
resp, body = self.post('policies', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_policies(self):
"""Lists the policies."""
resp, body = self.get('policies')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_policy(self, policy_id):
"""Lists out the given policy."""
@@ -50,7 +50,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_policy(self, policy_id, **kwargs):
"""Updates a policy.
@@ -63,11 +63,11 @@
resp, body = self.patch(url, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_policy(self, policy_id):
"""Deletes the policy."""
url = "policies/%s" % policy_id
resp, body = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/projects_client.py b/tempest/services/identity/v3/json/projects_client.py
index 2fa822f..dc553d0 100644
--- a/tempest/services/identity/v3/json/projects_client.py
+++ b/tempest/services/identity/v3/json/projects_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class ProjectsClient(service_client.ServiceClient):
+class ProjectsClient(rest_client.RestClient):
api_version = "v3"
def create_project(self, name, **kwargs):
@@ -37,7 +37,7 @@
resp, body = self.post('projects', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_projects(self, params=None):
url = "projects"
@@ -46,7 +46,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_project(self, project_id, **kwargs):
body = self.show_project(project_id)['project']
@@ -65,17 +65,17 @@
resp, body = self.patch('projects/%s' % project_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_project(self, project_id):
"""GET a Project."""
resp, body = self.get("projects/%s" % project_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_project(self, project_id):
"""Delete a project."""
resp, body = self.delete('projects/%s' % str(project_id))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/regions_client.py b/tempest/services/identity/v3/json/regions_client.py
index bc4b7a1..90dd9d7 100644
--- a/tempest/services/identity/v3/json/regions_client.py
+++ b/tempest/services/identity/v3/json/regions_client.py
@@ -20,10 +20,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class RegionsClient(service_client.ServiceClient):
+class RegionsClient(rest_client.RestClient):
api_version = "v3"
def create_region(self, region_id=None, **kwargs):
@@ -45,7 +45,7 @@
resp, body = method(url, req_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_region(self, region_id, **kwargs):
"""Updates a region.
@@ -57,7 +57,7 @@
resp, body = self.patch('regions/%s' % region_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_region(self, region_id):
"""Get region."""
@@ -65,7 +65,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_regions(self, params=None):
"""List regions."""
@@ -75,10 +75,10 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_region(self, region_id):
"""Delete region."""
resp, body = self.delete('regions/%s' % region_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/roles_client.py b/tempest/services/identity/v3/json/roles_client.py
new file mode 100644
index 0000000..bdb0490
--- /dev/null
+++ b/tempest/services/identity/v3/json/roles_client.py
@@ -0,0 +1,315 @@
+# Copyright 2016 Red Hat, 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.
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+
+class RolesClient(rest_client.RestClient):
+ api_version = "v3"
+
+ def create_role(self, **kwargs):
+ """Create a Role.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#createRole
+ """
+ post_body = json.dumps({'role': kwargs})
+ resp, body = self.post('roles', post_body)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_role(self, role_id):
+ """GET a Role."""
+ resp, body = self.get('roles/%s' % str(role_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_roles(self):
+ """Get the list of Roles."""
+ resp, body = self.get("roles")
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def update_role(self, role_id, **kwargs):
+ """Update a Role.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#updateRole
+ """
+ post_body = json.dumps({'role': kwargs})
+ resp, body = self.patch('roles/%s' % str(role_id), post_body)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role(self, role_id):
+ """Delete a role."""
+ resp, body = self.delete('roles/%s' % str(role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def assign_user_role_on_project(self, project_id, user_id, role_id):
+ """Add roles to a user on a project."""
+ resp, body = self.put('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def assign_user_role_on_domain(self, domain_id, user_id, role_id):
+ """Add roles to a user on a domain."""
+ resp, body = self.put('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_user_roles_on_project(self, project_id, user_id):
+ """list roles of a user on a project."""
+ resp, body = self.get('projects/%s/users/%s/roles' %
+ (project_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_user_roles_on_domain(self, domain_id, user_id):
+ """list roles of a user on a domain."""
+ resp, body = self.get('domains/%s/users/%s/roles' %
+ (domain_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_user_on_project(self, project_id, user_id, role_id):
+ """Delete role of a user on a project."""
+ resp, body = self.delete('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_user_on_domain(self, domain_id, user_id, role_id):
+ """Delete role of a user on a domain."""
+ resp, body = self.delete('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_role_existence_on_project(self, project_id,
+ user_id, role_id):
+ """Check role of a user on a project."""
+ resp, body = self.head('projects/%s/users/%s/roles/%s' %
+ (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def check_user_role_existence_on_domain(self, domain_id,
+ user_id, role_id):
+ """Check role of a user on a domain."""
+ resp, body = self.head('domains/%s/users/%s/roles/%s' %
+ (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def assign_group_role_on_project(self, project_id, group_id, role_id):
+ """Add roles to a user on a project."""
+ resp, body = self.put('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def assign_group_role_on_domain(self, domain_id, group_id, role_id):
+ """Add roles to a user on a domain."""
+ resp, body = self.put('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_group_roles_on_project(self, project_id, group_id):
+ """list roles of a user on a project."""
+ resp, body = self.get('projects/%s/groups/%s/roles' %
+ (project_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_group_roles_on_domain(self, domain_id, group_id):
+ """list roles of a user on a domain."""
+ resp, body = self.get('domains/%s/groups/%s/roles' %
+ (domain_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_group_on_project(self, project_id, group_id, role_id):
+ """Delete role of a user on a project."""
+ resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def delete_role_from_group_on_domain(self, domain_id, group_id, role_id):
+ """Delete role of a user on a domain."""
+ resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_role_from_group_on_project_existence(self, project_id,
+ group_id, role_id):
+ """Check role of a user on a project."""
+ resp, body = self.head('projects/%s/groups/%s/roles/%s' %
+ (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def check_role_from_group_on_domain_existence(self, domain_id,
+ group_id, role_id):
+ """Check role of a user on a domain."""
+ resp, body = self.head('domains/%s/groups/%s/roles/%s' %
+ (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def assign_inherited_role_on_domains_user(
+ self, domain_id, user_id, role_id):
+ """Assigns a role to a user on projects owned by a domain."""
+ resp, body = self.put(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def revoke_inherited_role_from_user_on_domain(
+ self, domain_id, user_id, role_id):
+ """Revokes an inherited project role from a user on a domain."""
+ resp, body = self.delete(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_inherited_project_role_for_user_on_domain(
+ self, domain_id, user_id):
+ """Lists the inherited project roles on a domain for a user."""
+ resp, body = self.get(
+ "OS-INHERIT/domains/%s/users/%s/roles/inherited_to_projects"
+ % (domain_id, user_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_inherited_project_role_on_domain(
+ self, domain_id, user_id, role_id):
+ """Checks whether a user has an inherited project role on a domain."""
+ resp, body = self.head(
+ "OS-INHERIT/domains/%s/users/%s/roles/%s/inherited_to_projects"
+ % (domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def assign_inherited_role_on_domains_group(
+ self, domain_id, group_id, role_id):
+ """Assigns a role to a group on projects owned by a domain."""
+ resp, body = self.put(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def revoke_inherited_role_from_group_on_domain(
+ self, domain_id, group_id, role_id):
+ """Revokes an inherited project role from a group on a domain."""
+ resp, body = self.delete(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_inherited_project_role_for_group_on_domain(
+ self, domain_id, group_id):
+ """Lists the inherited project roles on a domain for a group."""
+ resp, body = self.get(
+ "OS-INHERIT/domains/%s/groups/%s/roles/inherited_to_projects"
+ % (domain_id, group_id))
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_group_inherited_project_role_on_domain(
+ self, domain_id, group_id, role_id):
+ """Checks whether a group has an inherited project role on a domain."""
+ resp, body = self.head(
+ "OS-INHERIT/domains/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def assign_inherited_role_on_projects_user(
+ self, project_id, user_id, role_id):
+ """Assigns a role to a user on projects in a subtree."""
+ resp, body = self.put(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def revoke_inherited_role_from_user_on_project(
+ self, project_id, user_id, role_id):
+ """Revokes an inherited role from a user on a project."""
+ resp, body = self.delete(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_user_has_flag_on_inherited_to_project(
+ self, project_id, user_id, role_id):
+ """Checks whether a user has a role assignment"""
+ """with the inherited_to_projects flag on a project."""
+ resp, body = self.head(
+ "OS-INHERIT/projects/%s/users/%s/roles/%s/inherited_to_projects"
+ % (project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
+
+ def assign_inherited_role_on_projects_group(
+ self, project_id, group_id, role_id):
+ """Assigns a role to a group on projects in a subtree."""
+ resp, body = self.put(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def revoke_inherited_role_from_group_on_project(
+ self, project_id, group_id, role_id):
+ """Revokes an inherited role from a group on a project."""
+ resp, body = self.delete(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
+ def check_group_has_flag_on_inherited_to_project(
+ self, project_id, group_id, role_id):
+ """Checks whether a group has a role assignment"""
+ """with the inherited_to_projects flag on a project."""
+ resp, body = self.head(
+ "OS-INHERIT/projects/%s/groups/%s/roles/%s/inherited_to_projects"
+ % (project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/services/identity/v3/json/services_client.py b/tempest/services/identity/v3/json/services_client.py
index dd65f1d..e863016 100644
--- a/tempest/services/identity/v3/json/services_client.py
+++ b/tempest/services/identity/v3/json/services_client.py
@@ -19,10 +19,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class ServicesClient(service_client.ServiceClient):
+class ServicesClient(rest_client.RestClient):
api_version = "v3"
def update_service(self, service_id, **kwargs):
@@ -35,7 +35,7 @@
resp, body = self.patch('services/%s' % service_id, patch_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_service(self, service_id):
"""Get Service."""
@@ -43,7 +43,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_service(self, **kwargs):
"""Creates a service.
@@ -55,16 +55,16 @@
resp, body = self.post("services", body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_service(self, serv_id):
url = "services/" + serv_id
resp, body = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_services(self):
resp, body = self.get('services')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/trusts_client.py b/tempest/services/identity/v3/json/trusts_client.py
index 42b2bdb..dedee05 100644
--- a/tempest/services/identity/v3/json/trusts_client.py
+++ b/tempest/services/identity/v3/json/trusts_client.py
@@ -14,10 +14,10 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class TrustsClient(service_client.ServiceClient):
+class TrustsClient(rest_client.RestClient):
api_version = "v3"
def create_trust(self, **kwargs):
@@ -30,13 +30,13 @@
resp, body = self.post('OS-TRUST/trusts', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_trust(self, trust_id):
"""Deletes a trust."""
resp, body = self.delete("OS-TRUST/trusts/%s" % trust_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_trusts(self, trustor_user_id=None, trustee_user_id=None):
"""GET trusts."""
@@ -50,21 +50,21 @@
resp, body = self.get("OS-TRUST/trusts")
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_trust(self, trust_id):
"""GET trust."""
resp, body = self.get("OS-TRUST/trusts/%s" % trust_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_trust_roles(self, trust_id):
"""GET roles delegated by a trust."""
resp, body = self.get("OS-TRUST/trusts/%s/roles" % trust_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_trust_role(self, trust_id, role_id):
"""GET role delegated by a trust."""
@@ -72,11 +72,11 @@
% (trust_id, role_id))
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def check_trust_role(self, trust_id, role_id):
"""HEAD Check if role is delegated by a trust."""
resp, body = self.head("OS-TRUST/trusts/%s/roles/%s"
% (trust_id, role_id))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/identity/v3/json/users_clients.py b/tempest/services/identity/v3/json/users_clients.py
index 85c2e79..3ab8eab 100644
--- a/tempest/services/identity/v3/json/users_clients.py
+++ b/tempest/services/identity/v3/json/users_clients.py
@@ -15,10 +15,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class UsersV3Client(service_client.ServiceClient):
+class UsersClient(rest_client.RestClient):
api_version = "v3"
def create_user(self, user_name, password=None, project_id=None,
@@ -41,7 +41,7 @@
resp, body = self.post('users', post_body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_user(self, user_id, name, **kwargs):
"""Updates a user."""
@@ -70,7 +70,7 @@
resp, body = self.patch('users/%s' % user_id, post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_user_password(self, user_id, **kwargs):
"""Update a user password
@@ -81,14 +81,14 @@
update_user = json.dumps({'user': kwargs})
resp, _ = self.post('users/%s/password' % user_id, update_user)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def list_user_projects(self, user_id):
"""Lists the projects on which a user has roles assigned."""
resp, body = self.get('users/%s/projects' % user_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_users(self, params=None):
"""Get the list of users."""
@@ -98,24 +98,24 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_user(self, user_id):
"""Deletes a User."""
resp, body = self.delete("users/%s" % user_id)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_user_groups(self, user_id):
"""Lists groups which a user belongs to."""
resp, body = self.get('users/%s/groups' % user_id)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index b581203..3f256ec 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -24,34 +24,22 @@
from six.moves.urllib import parse as urllib
from tempest.common import glance_http
-from tempest.common import service_client
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib.common.utils import misc as misc_utils
from tempest.lib import exceptions as lib_exc
LOG = logging.getLogger(__name__)
-class ImagesClient(service_client.ServiceClient):
+class ImagesClient(rest_client.RestClient):
- 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, trace_requests=None):
+ def __init__(self, auth_provider, catalog_type, region, **kwargs):
super(ImagesClient, self).__init__(
- auth_provider,
- 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,
- trace_requests=trace_requests)
+ auth_provider, catalog_type, region, **kwargs)
self._http = None
- self.dscv = disable_ssl_certificate_validation
- self.ca_certs = ca_certs
+ self.dscv = kwargs.get("disable_ssl_certificate_validation")
+ self.ca_certs = kwargs.get("ca_certs")
def _image_meta_from_headers(self, headers):
meta = {'properties': {}}
@@ -130,7 +118,7 @@
self._error_checker('POST', '/v1/images', headers, data, resp,
body_iter)
body = json.loads(''.join([c for c in body_iter]))
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def _update_with_data(self, image_id, headers, data):
url = '/v1/images/%s' % image_id
@@ -139,7 +127,7 @@
self._error_checker('PUT', url, headers, data,
resp, body_iter)
body = json.loads(''.join([c for c in body_iter]))
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
@property
def http(self):
@@ -158,7 +146,7 @@
resp, body = self.post('v1/images', None, headers)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_image(self, image_id, **kwargs):
headers = {}
@@ -172,13 +160,13 @@
resp, body = self.put(url, None, headers)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_image(self, image_id):
url = 'v1/images/%s' % image_id
resp, body = self.delete(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_images(self, detail=False, **kwargs):
"""Return a list of all images filtered by input parameters.
@@ -208,20 +196,20 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def get_image_meta(self, image_id):
url = 'v1/images/%s' % image_id
resp, __ = self.head(url)
self.expected_success(200, resp.status)
body = self._image_meta_from_headers(resp)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_image(self, image_id):
url = 'v1/images/%s' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyData(resp, body)
+ return rest_client.ResponseBodyData(resp, body)
def is_resource_deleted(self, id):
try:
@@ -240,7 +228,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_shared_images(self, tenant_id):
"""List shared images with the specified tenant"""
@@ -248,7 +236,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def add_member(self, member_id, image_id, **kwargs):
"""Add a member to an image.
@@ -260,13 +248,13 @@
body = json.dumps({'member': kwargs})
resp, __ = self.put(url, body)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def delete_member(self, member_id, image_id):
url = 'v1/images/%s/members/%s' % (image_id, member_id)
resp, __ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
# NOTE(afazekas): just for the wait function
def _get_image_status(self, image_id):
diff --git a/tempest/services/image/v2/json/images_client.py b/tempest/services/image/v2/json/images_client.py
index b4744e4..4e037af 100644
--- a/tempest/services/image/v2/json/images_client.py
+++ b/tempest/services/image/v2/json/images_client.py
@@ -17,30 +17,18 @@
from six.moves.urllib import parse as urllib
from tempest.common import glance_http
-from tempest.common import service_client
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class ImagesClientV2(service_client.ServiceClient):
+class ImagesClientV2(rest_client.RestClient):
- 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,
- trace_requests=None):
+ def __init__(self, auth_provider, catalog_type, region, **kwargs):
super(ImagesClientV2, self).__init__(
- auth_provider,
- 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,
- trace_requests=trace_requests)
+ auth_provider, catalog_type, region, **kwargs)
self._http = None
- self.dscv = disable_ssl_certificate_validation
- self.ca_certs = ca_certs
+ self.dscv = kwargs.get("disable_ssl_certificate_validation")
+ self.ca_certs = kwargs.get("ca_certs")
def _get_http(self):
return glance_http.HTTPClient(auth_provider=self.auth_provider,
@@ -66,7 +54,7 @@
resp, body = self.patch('v2/images/%s' % image_id, data, headers)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_image(self, **kwargs):
"""Create an image.
@@ -78,25 +66,25 @@
resp, body = self.post('v2/images', data)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def deactivate_image(self, image_id):
url = 'v2/images/%s/actions/deactivate' % image_id
resp, body = self.post(url, None)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def reactivate_image(self, image_id):
url = 'v2/images/%s/actions/reactivate' % image_id
resp, body = self.post(url, None)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_image(self, image_id):
url = 'v2/images/%s' % image_id
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def list_images(self, params=None):
url = 'v2/images'
@@ -107,14 +95,14 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_image(self, image_id):
url = 'v2/images/%s' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
try:
@@ -134,32 +122,32 @@
resp, body = self.http.raw_request('PUT', url, headers=headers,
body=data)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_image_file(self, image_id):
url = 'v2/images/%s/file' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBodyData(resp, body)
+ return rest_client.ResponseBodyData(resp, body)
def add_image_tag(self, image_id, tag):
url = 'v2/images/%s/tags/%s' % (image_id, tag)
resp, body = self.put(url, body=None)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_image_tag(self, image_id, tag):
url = 'v2/images/%s/tags/%s' % (image_id, tag)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def list_image_members(self, image_id):
url = 'v2/images/%s/members' % image_id
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_image_member(self, image_id, **kwargs):
"""Create an image member.
@@ -172,7 +160,7 @@
resp, body = self.post(url, data)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_image_member(self, image_id, member_id, **kwargs):
"""Update an image member.
@@ -185,33 +173,33 @@
resp, body = self.put(url, data)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_image_member(self, image_id, member_id):
url = 'v2/images/%s/members/%s' % (image_id, member_id)
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, json.loads(body))
+ return rest_client.ResponseBody(resp, json.loads(body))
def delete_image_member(self, image_id, member_id):
url = 'v2/images/%s/members/%s' % (image_id, member_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def show_schema(self, schema):
url = 'v2/schemas/%s' % schema
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_resource_types(self):
url = '/v2/metadefs/resource_types'
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_namespace(self, **kwargs):
"""Create a namespace.
@@ -223,14 +211,14 @@
resp, body = self.post('/v2/metadefs/namespaces', data)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_namespace(self, namespace):
url = '/v2/metadefs/namespaces/%s' % namespace
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_namespace(self, namespace, **kwargs):
"""Update a namespace.
@@ -247,10 +235,10 @@
resp, body = self.put(url, body=data)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_namespace(self, namespace):
url = '/v2/metadefs/namespaces/%s' % namespace
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
diff --git a/tempest/services/network/json/base.py b/tempest/services/network/json/base.py
deleted file mode 100644
index 6ebc245..0000000
--- a/tempest/services/network/json/base.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.common import service_client
-
-
-class BaseNetworkClient(service_client.ServiceClient):
-
- """Base class for Tempest REST clients for Neutron.
-
- Child classes use v2 of the Neutron API, since the V1 API has been
- removed from the code base.
- """
-
- version = '2.0'
- uri_prefix = "v2.0"
-
- def list_resources(self, uri, **filters):
- req_uri = self.uri_prefix + uri
- if filters:
- req_uri += '?' + urllib.urlencode(filters, doseq=1)
- resp, body = self.get(req_uri)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def delete_resource(self, uri):
- req_uri = self.uri_prefix + uri
- resp, body = self.delete(req_uri)
- self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def show_resource(self, uri, **fields):
- # fields is a dict which key is 'fields' and value is a
- # list of field's name. An example:
- # {'fields': ['id', 'name']}
- req_uri = self.uri_prefix + uri
- if fields:
- req_uri += '?' + urllib.urlencode(fields, doseq=1)
- resp, body = self.get(req_uri)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def create_resource(self, uri, post_data):
- req_uri = self.uri_prefix + uri
- req_post_data = json.dumps(post_data)
- resp, body = self.post(req_uri, req_post_data)
- body = json.loads(body)
- self.expected_success(201, resp.status)
- return service_client.ResponseBody(resp, body)
-
- def update_resource(self, uri, post_data):
- req_uri = self.uri_prefix + uri
- req_post_data = json.dumps(post_data)
- resp, body = self.put(req_uri, req_post_data)
- body = json.loads(body)
- self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 5106b73..bcef36b 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -15,7 +15,7 @@
from tempest import exceptions
from tempest.lib.common.utils import misc
from tempest.lib import exceptions as lib_exc
-from tempest.services.network.json import base
+from tempest.lib.services.network import base
class NetworkClient(base.BaseNetworkClient):
@@ -34,33 +34,6 @@
quotas
"""
- def create_bulk_network(self, **kwargs):
- """create bulk network
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#bulkCreateNetwork
- """
- uri = '/networks'
- return self.create_resource(uri, kwargs)
-
- def create_bulk_subnet(self, **kwargs):
- """create bulk subnet
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#bulkCreateSubnet
- """
- uri = '/subnets'
- return self.create_resource(uri, kwargs)
-
- def create_bulk_port(self, **kwargs):
- """create bulk port
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2.html#bulkCreatePorts
- """
- uri = '/ports'
- return self.create_resource(uri, kwargs)
-
def wait_for_resource_deletion(self, resource_type, id, client=None):
"""Waits for a resource to be deleted."""
start_time = int(time.time())
@@ -120,110 +93,10 @@
message = '(%s) %s' % (caller, message)
raise exceptions.TimeoutException(message)
- def create_router(self, name, admin_state_up=True, **kwargs):
- post_body = {'router': kwargs}
- post_body['router']['name'] = name
- post_body['router']['admin_state_up'] = admin_state_up
- uri = '/routers'
- return self.create_resource(uri, post_body)
-
- def _update_router(self, router_id, set_enable_snat, **kwargs):
- uri = '/routers/%s' % router_id
- body = self.show_resource(uri)
- update_body = {}
- update_body['name'] = kwargs.get('name', body['router']['name'])
- update_body['admin_state_up'] = kwargs.get(
- 'admin_state_up', body['router']['admin_state_up'])
- cur_gw_info = body['router']['external_gateway_info']
- if cur_gw_info:
- # TODO(kevinbenton): setting the external gateway info is not
- # allowed for a regular tenant. If the ability to update is also
- # merged, a test case for this will need to be added similar to
- # the SNAT case.
- cur_gw_info.pop('external_fixed_ips', None)
- if not set_enable_snat:
- 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)
- return self.update_resource(uri, update_body)
-
- def update_router(self, router_id, **kwargs):
- """Update a router leaving enable_snat to its default value."""
- # If external_gateway_info contains enable_snat the request will fail
- # with 404 unless executed with admin client, and therefore we instruct
- # _update_router to not set this attribute
- # NOTE(salv-orlando): The above applies as long as Neutron's default
- # policy is to restrict enable_snat usage to admins only.
- return self._update_router(router_id, set_enable_snat=False, **kwargs)
-
- def show_router(self, router_id, **fields):
- uri = '/routers/%s' % router_id
- return self.show_resource(uri, **fields)
-
- def delete_router(self, router_id):
- uri = '/routers/%s' % router_id
- return self.delete_resource(uri)
-
- def list_routers(self, **filters):
- uri = '/routers'
- return self.list_resources(uri, **filters)
-
- def update_router_with_snat_gw_info(self, router_id, **kwargs):
- """Update a router passing also the enable_snat attribute.
-
- This method must be execute with admin credentials, otherwise the API
- call will return a 404 error.
- """
- return self._update_router(router_id, set_enable_snat=True, **kwargs)
-
- def add_router_interface(self, router_id, **kwargs):
- """Add router interface.
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#addRouterInterface
- """
- uri = '/routers/%s/add_router_interface' % router_id
- return self.update_resource(uri, kwargs)
-
- def remove_router_interface(self, router_id, **kwargs):
- """Remove router interface.
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#removeRouterInterface
- """
- uri = '/routers/%s/remove_router_interface' % router_id
- return self.update_resource(uri, kwargs)
-
def list_router_interfaces(self, uuid):
uri = '/ports?device_id=%s' % uuid
return self.list_resources(uri)
- def list_l3_agents_hosting_router(self, router_id):
- uri = '/routers/%s/l3-agents' % router_id
- return self.list_resources(uri)
-
def list_dhcp_agent_hosting_network(self, network_id):
uri = '/networks/%s/dhcp-agents' % network_id
return self.list_resources(uri)
-
- def update_extra_routes(self, router_id, **kwargs):
- """Update Extra routes.
-
- Available params: see http://developer.openstack.org/
- api-ref-networking-v2-ext.html#updateExtraRoutes
- """
- uri = '/routers/%s' % router_id
- put_body = {'router': kwargs}
- return self.update_resource(uri, put_body)
-
- def delete_extra_routes(self, router_id):
- uri = '/routers/%s' % router_id
- put_body = {
- 'router': {
- 'routes': None
- }
- }
- return self.update_resource(uri, put_body)
diff --git a/tempest/services/network/json/routers_client.py b/tempest/services/network/json/routers_client.py
new file mode 100644
index 0000000..18442cf
--- /dev/null
+++ b/tempest/services/network/json/routers_client.py
@@ -0,0 +1,116 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.network import base
+
+
+class RoutersClient(base.BaseNetworkClient):
+
+ def create_router(self, name, admin_state_up=True, **kwargs):
+ post_body = {'router': kwargs}
+ post_body['router']['name'] = name
+ post_body['router']['admin_state_up'] = admin_state_up
+ uri = '/routers'
+ return self.create_resource(uri, post_body)
+
+ def _update_router(self, router_id, set_enable_snat, **kwargs):
+ uri = '/routers/%s' % router_id
+ body = self.show_resource(uri)
+ update_body = {}
+ update_body['name'] = kwargs.get('name', body['router']['name'])
+ update_body['admin_state_up'] = kwargs.get(
+ 'admin_state_up', body['router']['admin_state_up'])
+ cur_gw_info = body['router']['external_gateway_info']
+ if cur_gw_info:
+ # TODO(kevinbenton): setting the external gateway info is not
+ # allowed for a regular tenant. If the ability to update is also
+ # merged, a test case for this will need to be added similar to
+ # the SNAT case.
+ cur_gw_info.pop('external_fixed_ips', None)
+ if not set_enable_snat:
+ 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)
+ return self.update_resource(uri, update_body)
+
+ def update_router(self, router_id, **kwargs):
+ """Update a router leaving enable_snat to its default value."""
+ # If external_gateway_info contains enable_snat the request will fail
+ # with 404 unless executed with admin client, and therefore we instruct
+ # _update_router to not set this attribute
+ # NOTE(salv-orlando): The above applies as long as Neutron's default
+ # policy is to restrict enable_snat usage to admins only.
+ return self._update_router(router_id, set_enable_snat=False, **kwargs)
+
+ def show_router(self, router_id, **fields):
+ uri = '/routers/%s' % router_id
+ return self.show_resource(uri, **fields)
+
+ def delete_router(self, router_id):
+ uri = '/routers/%s' % router_id
+ return self.delete_resource(uri)
+
+ def list_routers(self, **filters):
+ uri = '/routers'
+ return self.list_resources(uri, **filters)
+
+ def update_extra_routes(self, router_id, **kwargs):
+ """Update Extra routes.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-networking-v2-ext.html#updateExtraRoutes
+ """
+ uri = '/routers/%s' % router_id
+ put_body = {'router': kwargs}
+ return self.update_resource(uri, put_body)
+
+ def delete_extra_routes(self, router_id):
+ uri = '/routers/%s' % router_id
+ put_body = {
+ 'router': {
+ 'routes': None
+ }
+ }
+ return self.update_resource(uri, put_body)
+
+ def update_router_with_snat_gw_info(self, router_id, **kwargs):
+ """Update a router passing also the enable_snat attribute.
+
+ This method must be execute with admin credentials, otherwise the API
+ call will return a 404 error.
+ """
+ return self._update_router(router_id, set_enable_snat=True, **kwargs)
+
+ def add_router_interface(self, router_id, **kwargs):
+ """Add router interface.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-networking-v2-ext.html#addRouterInterface
+ """
+ uri = '/routers/%s/add_router_interface' % router_id
+ return self.update_resource(uri, kwargs)
+
+ def remove_router_interface(self, router_id, **kwargs):
+ """Remove router interface.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-networking-v2-ext.html#removeRouterInterface
+ """
+ uri = '/routers/%s/remove_router_interface' % router_id
+ return self.update_resource(uri, kwargs)
+
+ def list_l3_agents_hosting_router(self, router_id):
+ uri = '/routers/%s/l3-agents' % router_id
+ return self.list_resources(uri)
diff --git a/tempest/services/network/json/security_group_rules_client.py b/tempest/services/network/json/security_group_rules_client.py
index b2ba5b2..944eba6 100644
--- a/tempest/services/network/json/security_group_rules_client.py
+++ b/tempest/services/network/json/security_group_rules_client.py
@@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.services.network.json import base
+from tempest.lib.services.network import base
class SecurityGroupRulesClient(base.BaseNetworkClient):
diff --git a/tempest/services/network/resources.py b/tempest/services/network/resources.py
index 0a7da92..5512075 100644
--- a/tempest/services/network/resources.py
+++ b/tempest/services/network/resources.py
@@ -39,6 +39,7 @@
self.client = kwargs.pop('client', None)
self.network_client = kwargs.pop('network_client', None)
self.networks_client = kwargs.pop('networks_client', None)
+ self.routers_client = kwargs.pop('routers_client', None)
self.subnets_client = kwargs.pop('subnets_client', None)
self.ports_client = kwargs.pop('ports_client', None)
super(DeletableResource, self).__init__(*args, **kwargs)
@@ -89,12 +90,12 @@
def add_to_router(self, router_id):
self._router_ids.add(router_id)
- self.network_client.add_router_interface(router_id,
+ self.routers_client.add_router_interface(router_id,
subnet_id=self.id)
def delete(self):
for router_id in self._router_ids.copy():
- self.network_client.remove_router_interface(router_id,
+ self.routers_client.remove_router_interface(router_id,
subnet_id=self.id)
self._router_ids.remove(router_id)
self.subnets_client.delete_subnet(self.id)
@@ -109,14 +110,14 @@
return self.update(external_gateway_info=dict())
def update(self, *args, **kwargs):
- result = self.client.update_router(self.id,
- *args,
- **kwargs)
+ result = self.routers_client.update_router(self.id,
+ *args,
+ **kwargs)
return super(DeletableRouter, self).update(**result['router'])
def delete(self):
self.unset_gateway()
- self.client.delete_router(self.id)
+ self.routers_client.delete_router(self.id)
class DeletableFloatingIp(DeletableResource):
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 2c7fe29..6012a92 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -18,10 +18,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class AccountClient(service_client.ServiceClient):
+class AccountClient(rest_client.RestClient):
def create_account(self, data=None,
params=None,
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index 73c25db..5a26bfc 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -18,10 +18,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class ContainerClient(service_client.ServiceClient):
+class ContainerClient(rest_client.RestClient):
def create_container(
self, container_name,
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 5890e33..9ad8c27 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -17,10 +17,10 @@
from six.moves import http_client as httplib
from six.moves.urllib import parse as urlparse
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class ObjectClient(service_client.ServiceClient):
+class ObjectClient(rest_client.RestClient):
def create_object(self, container, object_name, data,
params=None, metadata=None, headers=None):
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index c0f5309..6019cf5 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -19,12 +19,12 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class OrchestrationClient(service_client.ServiceClient):
+class OrchestrationClient(rest_client.RestClient):
def list_stacks(self, params=None):
"""Lists all stacks for a user."""
@@ -36,7 +36,7 @@
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_stack(self, name, disable_rollback=True, parameters=None,
timeout_mins=60, template=None, template_url=None,
@@ -56,7 +56,7 @@
resp, body = self.post(uri, headers=headers, body=body)
self.expected_success(201, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_stack(self, stack_identifier, name, disable_rollback=True,
parameters=None, timeout_mins=60, template=None,
@@ -75,7 +75,7 @@
uri = "stacks/%s" % stack_identifier
resp, body = self.put(uri, headers=headers, body=body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def _prepare_update_create(self, name, disable_rollback=True,
parameters=None, timeout_mins=60,
@@ -111,7 +111,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def suspend_stack(self, stack_identifier):
"""Suspend a stack."""
@@ -119,7 +119,7 @@
body = {'suspend': None}
resp, body = self.post(url, json.dumps(body))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def resume_stack(self, stack_identifier):
"""Resume a stack."""
@@ -127,7 +127,7 @@
body = {'resume': None}
resp, body = self.post(url, json.dumps(body))
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def list_resources(self, stack_identifier):
"""Returns the details of a single resource."""
@@ -135,7 +135,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_resource(self, stack_identifier, resource_name):
"""Returns the details of a single resource."""
@@ -143,13 +143,13 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_stack(self, stack_identifier):
"""Deletes the specified Stack."""
resp, _ = self.delete("stacks/%s" % str(stack_identifier))
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def wait_for_resource_status(self, stack_identifier, resource_name,
status, failure_pattern='^.*_FAILED$'):
@@ -224,7 +224,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_events(self, stack_identifier):
"""Returns list of all events for a stack."""
@@ -232,7 +232,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_resource_events(self, stack_identifier, resource_name):
"""Returns list of all events for a resource from stack."""
@@ -241,7 +241,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_event(self, stack_identifier, resource_name, event_id):
"""Returns the details of a single stack's event."""
@@ -250,7 +250,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_template(self, stack_identifier):
"""Returns the template for the stack."""
@@ -258,7 +258,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def _validate_template(self, post_body):
"""Returns the validation request result."""
@@ -266,7 +266,7 @@
resp, body = self.post('validate', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def validate_template(self, template, parameters=None):
"""Returns the validation result for a template with parameters."""
@@ -293,21 +293,21 @@
resp, body = self.get('resource_types')
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_resource_type(self, resource_type_name):
"""Return the schema of a resource type."""
url = 'resource_types/%s' % resource_type_name
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, json.loads(body))
+ return rest_client.ResponseBody(resp, json.loads(body))
def show_resource_type_template(self, resource_type_name):
"""Return the template of a resource type."""
url = 'resource_types/%s/template' % resource_type_name
resp, body = self.get(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, json.loads(body))
+ return rest_client.ResponseBody(resp, json.loads(body))
def create_software_config(self, name=None, config=None, group=None,
inputs=None, outputs=None, options=None):
@@ -318,7 +318,7 @@
resp, body = self.post(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_software_config(self, conf_id):
"""Returns a software configuration resource."""
@@ -326,14 +326,14 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_software_config(self, conf_id):
"""Deletes a specific software configuration."""
url = 'software_configs/%s' % str(conf_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def create_software_deploy(self, server_id=None, config_id=None,
action=None, status=None,
@@ -348,7 +348,7 @@
resp, body = self.post(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_software_deploy(self, deploy_id=None, server_id=None,
config_id=None, action=None, status=None,
@@ -363,7 +363,7 @@
resp, body = self.put(url, headers=headers, body=body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_software_deployments(self):
"""Returns a list of all deployments."""
@@ -371,7 +371,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_software_deployment(self, deploy_id):
"""Returns a specific software deployment."""
@@ -379,7 +379,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_software_deployment_metadata(self, server_id):
"""Return a config metadata for a specific server."""
@@ -387,14 +387,14 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_software_deploy(self, deploy_id):
"""Deletes a specific software deployment."""
url = 'software_deployments/%s' % str(deploy_id)
resp, _ = self.delete(url)
self.expected_success(204, resp.status)
- return service_client.ResponseBody(resp)
+ return rest_client.ResponseBody(resp)
def _prep_software_config_create(self, name=None, conf=None, group=None,
inputs=None, outputs=None, options=None):
diff --git a/tempest/services/telemetry/json/alarming_client.py b/tempest/services/telemetry/json/alarming_client.py
index ce14211..703efdf 100644
--- a/tempest/services/telemetry/json/alarming_client.py
+++ b/tempest/services/telemetry/json/alarming_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class AlarmingClient(service_client.ServiceClient):
+class AlarmingClient(rest_client.RestClient):
version = '2'
uri_prefix = "v2"
@@ -42,21 +42,21 @@
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBodyList(resp, body)
+ return rest_client.ResponseBodyList(resp, body)
def show_alarm(self, alarm_id):
uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_alarm_history(self, alarm_id):
uri = "%s/alarms/%s/history" % (self.uri_prefix, alarm_id)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBodyList(resp, body)
+ return rest_client.ResponseBodyList(resp, body)
def delete_alarm(self, alarm_id):
uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
@@ -64,7 +64,7 @@
self.expected_success(204, resp.status)
if body:
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_alarm(self, **kwargs):
uri = "%s/alarms" % self.uri_prefix
@@ -72,7 +72,7 @@
resp, body = self.post(uri, body)
self.expected_success(201, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_alarm(self, alarm_id, **kwargs):
uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
@@ -80,14 +80,14 @@
resp, body = self.put(uri, body)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_alarm_state(self, alarm_id):
uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBodyData(resp, body)
+ return rest_client.ResponseBodyData(resp, body)
def alarm_set_state(self, alarm_id, state):
uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
@@ -95,4 +95,4 @@
resp, body = self.put(uri, body)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBodyData(resp, body)
+ return rest_client.ResponseBodyData(resp, body)
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index abdeba2..df7d916 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class TelemetryClient(service_client.ServiceClient):
+class TelemetryClient(rest_client.RestClient):
version = '2'
uri_prefix = "v2"
@@ -36,7 +36,7 @@
resp, body = self.post(uri, body)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def _helper_list(self, uri, query=None, period=None):
uri_dict = {}
@@ -51,7 +51,7 @@
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBodyList(resp, body)
+ return rest_client.ResponseBodyList(resp, body)
def list_resources(self, query=None):
uri = '%s/resources' % self.uri_prefix
@@ -78,4 +78,4 @@
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/admin/base_hosts_client.py b/tempest/services/volume/base/admin/base_hosts_client.py
index 074f87f..382e9a8 100644
--- a/tempest/services/volume/base/admin/base_hosts_client.py
+++ b/tempest/services/volume/base/admin/base_hosts_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class BaseHostsClient(service_client.ServiceClient):
+class BaseHostsClient(rest_client.RestClient):
"""Client class to send CRUD Volume Hosts API requests"""
def list_hosts(self, **params):
@@ -32,4 +32,4 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/admin/base_quotas_client.py b/tempest/services/volume/base/admin/base_quotas_client.py
index e063a31..83816f2 100644
--- a/tempest/services/volume/base/admin/base_quotas_client.py
+++ b/tempest/services/volume/base/admin/base_quotas_client.py
@@ -15,10 +15,10 @@
from oslo_serialization import jsonutils
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class BaseQuotasClient(service_client.ServiceClient):
+class BaseQuotasClient(rest_client.RestClient):
"""Client class to send CRUD Volume Quotas API requests"""
TYPE = "json"
@@ -30,7 +30,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = jsonutils.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_quota_set(self, tenant_id, params=None):
"""List the quota set for a tenant."""
@@ -42,7 +42,7 @@
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = jsonutils.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_quota_usage(self, tenant_id):
"""List the quota set for a tenant."""
@@ -60,10 +60,10 @@
resp, body = self.put('os-quota-sets/%s' % tenant_id, put_body)
self.expected_success(200, resp.status)
body = jsonutils.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_quota_set(self, tenant_id):
"""Delete the tenant's quota set."""
resp, body = self.delete('os-quota-sets/%s' % tenant_id)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/admin/base_services_client.py b/tempest/services/volume/base/admin/base_services_client.py
index 3626469..861eb92 100644
--- a/tempest/services/volume/base/admin/base_services_client.py
+++ b/tempest/services/volume/base/admin/base_services_client.py
@@ -16,10 +16,10 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class BaseServicesClient(service_client.ServiceClient):
+class BaseServicesClient(rest_client.RestClient):
def list_services(self, **params):
url = 'os-services'
@@ -29,4 +29,4 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/admin/base_types_client.py b/tempest/services/volume/base/admin/base_types_client.py
index f117f0a..95ddff6 100644
--- a/tempest/services/volume/base/admin/base_types_client.py
+++ b/tempest/services/volume/base/admin/base_types_client.py
@@ -16,11 +16,11 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class BaseTypesClient(service_client.ServiceClient):
+class BaseTypesClient(rest_client.RestClient):
"""Client class to send CRUD Volume Types API requests"""
def is_resource_deleted(self, resource):
@@ -56,7 +56,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_volume_type(self, volume_id):
"""Returns the details of a single volume_type."""
@@ -64,7 +64,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_volume_type(self, **kwargs):
"""Create volume type.
@@ -76,13 +76,13 @@
resp, body = self.post('types', post_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_volume_type(self, volume_id):
"""Deletes the Specified Volume_type."""
resp, body = self.delete("types/%s" % str(volume_id))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_volume_types_extra_specs(self, vol_type_id, **params):
"""List all the volume_types extra specs created.
@@ -100,7 +100,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_volume_type_extra_specs(self, vol_type_id, extra_specs_name):
"""Returns the details of a single volume_type extra spec."""
@@ -109,7 +109,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_volume_type_extra_specs(self, vol_type_id, extra_specs):
"""Creates a new Volume_type extra spec.
@@ -122,14 +122,14 @@
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_volume_type_extra_specs(self, vol_id, extra_spec_name):
"""Deletes the Specified Volume_type extra spec."""
resp, body = self.delete("types/%s/extra_specs/%s" % (
(str(vol_id)), str(extra_spec_name)))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name,
extra_specs):
@@ -146,7 +146,7 @@
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_encryption_type(self, vol_type_id):
"""Get the volume encryption type for the specified volume type.
@@ -157,7 +157,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_encryption_type(self, vol_type_id, **kwargs):
"""Create encryption type.
@@ -171,11 +171,11 @@
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_encryption_type(self, vol_type_id):
"""Delete the encryption type for the specified volume-type."""
resp, body = self.delete(
"/types/%s/encryption/provider" % str(vol_type_id))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_availability_zone_client.py b/tempest/services/volume/base/base_availability_zone_client.py
index b63fdc2..1c2deba 100644
--- a/tempest/services/volume/base/base_availability_zone_client.py
+++ b/tempest/services/volume/base/base_availability_zone_client.py
@@ -15,13 +15,13 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class BaseAvailabilityZoneClient(service_client.ServiceClient):
+class BaseAvailabilityZoneClient(rest_client.RestClient):
def list_availability_zones(self):
resp, body = self.get('os-availability-zone')
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_backups_client.py b/tempest/services/volume/base/base_backups_client.py
index d6f2a50..780da7b 100644
--- a/tempest/services/volume/base/base_backups_client.py
+++ b/tempest/services/volume/base/base_backups_client.py
@@ -17,12 +17,12 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class BaseBackupsClient(service_client.ServiceClient):
+class BaseBackupsClient(rest_client.RestClient):
"""Client class to send CRUD Volume backup API requests"""
def create_backup(self, **kwargs):
@@ -31,7 +31,7 @@
resp, body = self.post('backups', post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def restore_backup(self, backup_id, **kwargs):
"""Restore volume from backup."""
@@ -39,13 +39,13 @@
resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_backup(self, backup_id):
"""Delete a backup of volume."""
resp, body = self.delete('backups/%s' % (str(backup_id)))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_backup(self, backup_id):
"""Returns the details of a single backup."""
@@ -53,7 +53,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_backups(self, detail=False):
"""Information for all the tenant's backups."""
@@ -63,7 +63,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def export_backup(self, backup_id):
"""Export backup metadata record."""
@@ -71,7 +71,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def import_backup(self, **kwargs):
"""Import backup metadata record."""
@@ -79,7 +79,7 @@
resp, body = self.post("backups/import_record", post_body)
body = json.loads(body)
self.expected_success(201, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def wait_for_backup_status(self, backup_id, status):
"""Waits for a Backup to reach a given status."""
diff --git a/tempest/services/volume/base/base_extensions_client.py b/tempest/services/volume/base/base_extensions_client.py
index afc3f6b..b90fe94 100644
--- a/tempest/services/volume/base/base_extensions_client.py
+++ b/tempest/services/volume/base/base_extensions_client.py
@@ -15,14 +15,14 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
+from tempest.lib.common import rest_client
-class BaseExtensionsClient(service_client.ServiceClient):
+class BaseExtensionsClient(rest_client.RestClient):
def list_extensions(self):
url = 'extensions'
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_qos_client.py b/tempest/services/volume/base/base_qos_client.py
index f68f9aa..2d9f02a 100644
--- a/tempest/services/volume/base/base_qos_client.py
+++ b/tempest/services/volume/base/base_qos_client.py
@@ -16,12 +16,12 @@
from oslo_serialization import jsonutils as json
-from tempest.common import service_client
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class BaseQosSpecsClient(service_client.ServiceClient):
+class BaseQosSpecsClient(rest_client.RestClient):
"""Client class to send CRUD QoS API requests"""
def is_resource_deleted(self, qos_id):
@@ -77,14 +77,14 @@
resp, body = self.post('qos-specs', post_body)
self.expected_success(200, resp.status)
body = json.loads(body)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_qos(self, qos_id, force=False):
"""Delete the specified QoS specification."""
resp, body = self.delete(
"qos-specs/%s?force=%s" % (str(qos_id), force))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_qos(self):
"""List all the QoS specifications created."""
@@ -92,7 +92,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_qos(self, qos_id):
"""Get the specified QoS specification."""
@@ -100,7 +100,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def set_qos_key(self, qos_id, **kwargs):
"""Set the specified keys/values of QoS specification.
@@ -112,7 +112,7 @@
resp, body = self.put('qos-specs/%s' % qos_id, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def unset_qos_key(self, qos_id, keys):
"""Unset the specified keys of QoS specification.
@@ -124,7 +124,7 @@
put_body = json.dumps({'keys': keys})
resp, body = self.put('qos-specs/%s/delete_keys' % qos_id, put_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def associate_qos(self, qos_id, vol_type_id):
"""Associate the specified QoS with specified volume-type."""
@@ -132,7 +132,7 @@
url += "?vol_type_id=%s" % vol_type_id
resp, body = self.get(url)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_association_qos(self, qos_id):
"""Get the association of the specified QoS specification."""
@@ -140,7 +140,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def disassociate_qos(self, qos_id, vol_type_id):
"""Disassociate the specified QoS with specified volume-type."""
@@ -148,11 +148,11 @@
url += "?vol_type_id=%s" % vol_type_id
resp, body = self.get(url)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def disassociate_all_qos(self, qos_id):
"""Disassociate the specified QoS with all associations."""
url = "qos-specs/%s/disassociate_all" % str(qos_id)
resp, body = self.get(url)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_snapshots_client.py b/tempest/services/volume/base/base_snapshots_client.py
index ed2a642..5e5637a 100644
--- a/tempest/services/volume/base/base_snapshots_client.py
+++ b/tempest/services/volume/base/base_snapshots_client.py
@@ -16,15 +16,15 @@
from oslo_serialization import jsonutils as json
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
LOG = logging.getLogger(__name__)
-class BaseSnapshotsClient(service_client.ServiceClient):
+class BaseSnapshotsClient(rest_client.RestClient):
"""Base Client class to send CRUD Volume API requests."""
create_resp = 200
@@ -40,7 +40,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_snapshot(self, snapshot_id):
"""Returns the details of a single snapshot."""
@@ -48,7 +48,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_snapshot(self, **kwargs):
"""Creates a new snapshot.
@@ -60,7 +60,7 @@
resp, body = self.post('snapshots', post_body)
body = json.loads(body)
self.expected_success(self.create_resp, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_snapshot(self, snapshot_id, **kwargs):
"""Updates a snapshot."""
@@ -68,7 +68,7 @@
resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
# NOTE(afazekas): just for the wait function
def _get_snapshot_status(self, snapshot_id):
@@ -111,7 +111,7 @@
"""Delete Snapshot."""
resp, body = self.delete("snapshots/%s" % str(snapshot_id))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def is_resource_deleted(self, id):
try:
@@ -130,7 +130,7 @@
post_body = json.dumps({'os-reset_status': {"status": status}})
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_snapshot_status(self, snapshot_id, **kwargs):
"""Update the specified snapshot's status."""
@@ -143,7 +143,7 @@
url = 'snapshots/%s/action' % str(snapshot_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_snapshot_metadata(self, snapshot_id, metadata):
"""Create metadata for the snapshot."""
@@ -152,7 +152,7 @@
resp, body = self.post(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_snapshot_metadata(self, snapshot_id):
"""Get metadata of the snapshot."""
@@ -160,7 +160,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_snapshot_metadata(self, snapshot_id, **kwargs):
"""Update metadata for the snapshot."""
@@ -173,7 +173,7 @@
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_snapshot_metadata_item(self, snapshot_id, id, **kwargs):
"""Update metadata item for the snapshot."""
@@ -186,18 +186,18 @@
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_snapshot_metadata_item(self, snapshot_id, id):
"""Delete metadata item for the snapshot."""
url = "snapshots/%s/metadata/%s" % (str(snapshot_id), str(id))
resp, body = self.delete(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def force_delete_snapshot(self, snapshot_id):
"""Force Delete Snapshot."""
post_body = json.dumps({'os-force_delete': {}})
resp, body = self.post('snapshots/%s/action' % snapshot_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/services/volume/base/base_volumes_client.py b/tempest/services/volume/base/base_volumes_client.py
index 5c0c7f7..f638bb6 100644
--- a/tempest/services/volume/base/base_volumes_client.py
+++ b/tempest/services/volume/base/base_volumes_client.py
@@ -17,12 +17,12 @@
import six
from six.moves.urllib import parse as urllib
-from tempest.common import service_client
from tempest.common import waiters
+from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
-class BaseVolumesClient(service_client.ServiceClient):
+class BaseVolumesClient(rest_client.RestClient):
"""Base client class to send CRUD Volume API requests"""
create_resp = 200
@@ -61,7 +61,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_volume(self, volume_id):
"""Returns the details of a single volume."""
@@ -69,7 +69,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_volume(self, **kwargs):
"""Creates a new Volume.
@@ -83,7 +83,7 @@
resp, body = self.post('volumes', post_body)
body = json.loads(body)
self.expected_success(self.create_resp, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_volume(self, volume_id, **kwargs):
"""Updates the Specified Volume."""
@@ -91,13 +91,13 @@
resp, body = self.put('volumes/%s' % volume_id, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
resp, body = self.delete("volumes/%s" % str(volume_id))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def upload_volume(self, volume_id, **kwargs):
"""Uploads a volume in Glance."""
@@ -106,7 +106,7 @@
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def attach_volume(self, volume_id, **kwargs):
"""Attaches a volume to a given instance on a given mountpoint."""
@@ -114,7 +114,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def set_bootable_volume(self, volume_id, **kwargs):
"""set a bootable flag for a volume - true or false."""
@@ -122,7 +122,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def detach_volume(self, volume_id):
"""Detaches a volume from an instance."""
@@ -130,7 +130,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def reserve_volume(self, volume_id):
"""Reserves a volume."""
@@ -138,7 +138,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def unreserve_volume(self, volume_id):
"""Restore a reserved volume ."""
@@ -146,7 +146,7 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def wait_for_volume_status(self, volume_id, status):
"""Waits for a Volume to reach a given status."""
@@ -170,14 +170,14 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def reset_volume_status(self, volume_id, **kwargs):
"""Reset the Specified Volume's Status."""
post_body = json.dumps({'os-reset_status': kwargs})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def volume_begin_detaching(self, volume_id):
"""Volume Begin Detaching."""
@@ -185,7 +185,7 @@
post_body = json.dumps({'os-begin_detaching': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def volume_roll_detaching(self, volume_id):
"""Volume Roll Detaching."""
@@ -193,7 +193,7 @@
post_body = json.dumps({'os-roll_detaching': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_volume_transfer(self, **kwargs):
"""Create a volume transfer."""
@@ -201,7 +201,7 @@
resp, body = self.post('os-volume-transfer', post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_volume_transfer(self, transfer_id):
"""Returns the details of a volume transfer."""
@@ -209,7 +209,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def list_volume_transfers(self, **params):
"""List all the volume transfers created."""
@@ -219,13 +219,13 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_volume_transfer(self, transfer_id):
"""Delete a volume transfer."""
resp, body = self.delete("os-volume-transfer/%s" % str(transfer_id))
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def accept_volume_transfer(self, transfer_id, **kwargs):
"""Accept a volume transfer."""
@@ -234,7 +234,7 @@
resp, body = self.post(url, post_body)
body = json.loads(body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_volume_readonly(self, volume_id, **kwargs):
"""Update the Specified Volume readonly."""
@@ -242,14 +242,14 @@
url = 'volumes/%s/action' % (volume_id)
resp, body = self.post(url, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def force_delete_volume(self, volume_id):
"""Force Delete Volume."""
post_body = json.dumps({'os-force_delete': {}})
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
self.expected_success(202, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def create_volume_metadata(self, volume_id, metadata):
"""Create metadata for the volume."""
@@ -258,7 +258,7 @@
resp, body = self.post(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def show_volume_metadata(self, volume_id):
"""Get metadata of the volume."""
@@ -266,7 +266,7 @@
resp, body = self.get(url)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_volume_metadata(self, volume_id, metadata):
"""Update metadata for the volume."""
@@ -275,7 +275,7 @@
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def update_volume_metadata_item(self, volume_id, id, meta_item):
"""Update metadata item for the volume."""
@@ -284,14 +284,14 @@
resp, body = self.put(url, put_body)
body = json.loads(body)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def delete_volume_metadata_item(self, volume_id, id):
"""Delete metadata item for the volume."""
url = "volumes/%s/metadata/%s" % (str(volume_id), str(id))
resp, body = self.delete(url)
self.expected_success(200, resp.status)
- return service_client.ResponseBody(resp, body)
+ return rest_client.ResponseBody(resp, body)
def retype_volume(self, volume_id, **kwargs):
"""Updates volume with new volume type."""
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 468578d..382b851 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -153,7 +153,7 @@
else:
identity_client = admin_manager.identity_v3_client
projects_client = admin_manager.projects_client
- roles_client = None
+ roles_client = admin_manager.roles_v3_client
users_client = admin_manager.users_v3_client
domains_client = admin_manager.domains_client
domain = (identity_client.auth_provider.credentials.
diff --git a/tempest/stress/stressaction.py b/tempest/stress/stressaction.py
index c8bd652..cf0a08a 100644
--- a/tempest/stress/stressaction.py
+++ b/tempest/stress/stressaction.py
@@ -85,8 +85,8 @@
finally:
shared_statistic['runs'] += 1
if self.stop_on_error and (shared_statistic['fails'] > 1):
- self.logger.warn("Stop process due to"
- "\"stop-on-error\" argument")
+ self.logger.warning("Stop process due to"
+ "\"stop-on-error\" argument")
self.tearDown()
sys.exit(1)
diff --git a/tempest/test.py b/tempest/test.py
index 45b818f..fe3c770 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -180,6 +180,19 @@
return False
+def is_scheduler_filter_enabled(filter_name):
+ """Check the list of enabled compute scheduler filters from config. """
+
+ filters = CONF.compute_feature_enabled.scheduler_available_filters
+ if len(filters) == 0:
+ return False
+ if 'all' in filters:
+ return True
+ if filter_name in filters:
+ return True
+ return False
+
+
at_exit_set = set()
@@ -236,6 +249,9 @@
# Client manager class to use in this test case.
client_manager = clients.Manager
+ # A way to adjust slow test classes
+ TIMEOUT_SCALING_FACTOR = 1
+
@classmethod
def setUpClass(cls):
# It should never be overridden by descendants
@@ -406,7 +422,7 @@
at_exit_set.add(self.__class__)
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
try:
- test_timeout = int(test_timeout)
+ test_timeout = int(test_timeout) * self.TIMEOUT_SCALING_FACTOR
except ValueError:
test_timeout = 0
if test_timeout > 0:
@@ -445,9 +461,9 @@
domains_client = None
else:
client = self.os_admin.identity_v3_client
- project_client = self.os_adm.projects_client
users_client = self.os_admin.users_v3_client
- roles_client = None
+ project_client = self.os_admin.projects_client
+ roles_client = self.os_admin.roles_v3_client
domains_client = self.os_admin.domains_client
try:
diff --git a/tempest/tests/cmd/test_javelin.py b/tempest/tests/cmd/test_javelin.py
index 3380f84..dc7b434 100644
--- a/tempest/tests/cmd/test_javelin.py
+++ b/tempest/tests/cmd/test_javelin.py
@@ -250,7 +250,7 @@
def test_create_router(self):
- self.fake_client.networks.list_routers.return_value = {'routers': []}
+ self.fake_client.routers.list_routers.return_value = {'routers': []}
self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
return_value=self.fake_client))
@@ -260,7 +260,7 @@
mocked_function.assert_called_once_with(self.fake_object['name'])
def test_create_router_existing(self):
- self.fake_client.networks.list_routers.return_value = {
+ self.fake_client.routers.list_routers.return_value = {
'routers': [self.fake_object]}
self.useFixture(mockpatch.PatchObject(javelin, "client_for_user",
return_value=self.fake_client))
@@ -405,7 +405,7 @@
javelin.destroy_routers([self.fake_object])
- mocked_function = self.fake_client.networks.delete_router
+ mocked_function = self.fake_client.routers.delete_router
mocked_function.assert_called_once_with(
self.fake_object['router_id'])
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 1048a52..685a0b3 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -36,9 +36,8 @@
testr_conf_file = init.TESTR_CONF % (top_level_path, discover_path)
conf_path = conf_dir.join('.testr.conf')
- conf_file = open(conf_path, 'r')
- self.addCleanup(conf_file.close)
- self.assertEqual(conf_file.read(), testr_conf_file)
+ with open(conf_path, 'r') as conf_file:
+ self.assertEqual(conf_file.read(), testr_conf_file)
def test_generate_sample_config(self):
local_dir = self.useFixture(fixtures.TempDir())
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index 059269e..be4a6ee 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -18,9 +18,9 @@
from tempest.common import credentials_factory as credentials
from tempest.common import dynamic_creds
-from tempest.common import service_client
from tempest import config
from tempest import exceptions
+from tempest.lib.common import rest_client
from tempest.lib.services.identity.v2 import token_client as json_token_client
from tempest.services.identity.v2.json import identity_client as \
json_iden_client
@@ -31,6 +31,7 @@
from tempest.services.identity.v2.json import users_client as \
json_users_client
from tempest.services.network.json import network_client as json_network_client
+from tempest.services.network.json import routers_client
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests import fake_http
@@ -74,7 +75,7 @@
user_fix = self.useFixture(mockpatch.PatchObject(
json_users_client.UsersClient,
'create_user',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200, {'user': {'id': id, 'name': name}}))))
return user_fix
@@ -82,7 +83,7 @@
tenant_fix = self.useFixture(mockpatch.PatchObject(
json_tenants_client.TenantsClient,
'create_tenant',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200, {'tenant': {'id': id, 'name': name}}))))
return tenant_fix
@@ -90,7 +91,7 @@
roles_fix = self.useFixture(mockpatch.PatchObject(
json_roles_client.RolesClient,
'list_roles',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200,
{'roles': [{'id': id, 'name': name},
{'id': '1', 'name': 'FakeRole'},
@@ -101,7 +102,7 @@
roles_fix = self.useFixture(mockpatch.PatchObject(
json_roles_client.RolesClient,
'list_roles',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200,
{'roles': [{'id': '1234', 'name': 'role1'},
{'id': '1', 'name': 'FakeRole'},
@@ -112,7 +113,7 @@
tenant_fix = self.useFixture(mockpatch.PatchObject(
json_roles_client.RolesClient,
'assign_user_role',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200, {}))))
return tenant_fix
@@ -120,7 +121,7 @@
roles_fix = self.useFixture(mockpatch.PatchObject(
json_roles_client.RolesClient,
'list_roles',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200, {'roles': [{'id': '1',
'name': 'FakeRole'}]}))))
return roles_fix
@@ -129,7 +130,7 @@
ec2_creds_fix = self.useFixture(mockpatch.PatchObject(
json_users_client.UsersClient,
'list_user_ec2_credentials',
- return_value=(service_client.ResponseBody
+ return_value=(rest_client.ResponseBody
(200, {'credentials': [{
'access': 'fake_access',
'secret': 'fake_secret',
@@ -154,7 +155,7 @@
def _mock_router_create(self, id, name):
router_fix = self.useFixture(mockpatch.PatchObject(
- json_network_client.NetworkClient,
+ routers_client.RoutersClient,
'create_router',
return_value={'router': {'id': id, 'name': name}}))
return router_fix
@@ -295,7 +296,7 @@
subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(creds.network_admin_client,
+ router = mock.patch.object(creds.routers_admin_client,
'delete_router')
router_mock = router.start()
@@ -321,7 +322,7 @@
self._mock_subnet_create(creds, '1234', 'fake_subnet')
self._mock_router_create('1234', 'fake_router')
router_interface_mock = self.patch(
- 'tempest.services.network.json.network_client.NetworkClient.'
+ 'tempest.services.network.json.routers_client.RoutersClient.'
'add_router_interface')
primary_creds = creds.get_primary_creds()
router_interface_mock.assert_called_once_with('1234', subnet_id='1234')
@@ -353,7 +354,7 @@
self._mock_subnet_create(creds, '1234', 'fake_subnet')
self._mock_router_create('1234', 'fake_router')
router_interface_mock = self.patch(
- 'tempest.services.network.json.network_client.NetworkClient.'
+ 'tempest.services.network.json.routers_client.RoutersClient.'
'add_router_interface')
creds.get_primary_creds()
router_interface_mock.assert_called_once_with('1234', subnet_id='1234')
@@ -386,11 +387,11 @@
subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(creds.network_admin_client,
+ router = mock.patch.object(creds.routers_admin_client,
'delete_router')
router_mock = router.start()
remove_router_interface_mock = self.patch(
- 'tempest.services.network.json.network_client.NetworkClient.'
+ 'tempest.services.network.json.routers_client.RoutersClient.'
'remove_router_interface')
return_values = ({'status': 200}, {'ports': []})
port_list_mock = mock.patch.object(creds.ports_admin_client,
@@ -461,7 +462,7 @@
self._mock_subnet_create(creds, '1234', 'fake_alt_subnet')
self._mock_router_create('1234', 'fake_alt_router')
router_interface_mock = self.patch(
- 'tempest.services.network.json.network_client.NetworkClient.'
+ 'tempest.services.network.json.routers_client.RoutersClient.'
'add_router_interface')
alt_creds = creds.get_alt_creds()
router_interface_mock.assert_called_once_with('1234', subnet_id='1234')
@@ -485,7 +486,7 @@
self._mock_subnet_create(creds, '1234', 'fake_admin_subnet')
self._mock_router_create('1234', 'fake_admin_router')
router_interface_mock = self.patch(
- 'tempest.services.network.json.network_client.NetworkClient.'
+ 'tempest.services.network.json.routers_client.RoutersClient.'
'add_router_interface')
self._mock_list_roles('123456', 'admin')
admin_creds = creds.get_admin_creds()
@@ -521,7 +522,7 @@
subnet = mock.patch.object(creds.subnets_admin_client,
'delete_subnet')
subnet_mock = subnet.start()
- router = mock.patch.object(creds.network_admin_client,
+ router = mock.patch.object(creds.routers_admin_client,
'delete_router')
router_mock = router.start()
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
deleted file mode 100644
index 7e9ff9d..0000000
--- a/tempest/tests/common/test_service_clients.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import mock
-import random
-import six
-
-from tempest.services.baremetal.v1.json import baremetal_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 policies_client
-from tempest.services.identity.v3.json import regions_client
-from tempest.services.identity.v3.json import services_client
-from tempest.services.image.v1.json import images_client
-from tempest.services.image.v2.json import images_client as images_v2_client
-from tempest.services.network.json import network_client
-from tempest.services.object_storage import account_client
-from tempest.services.object_storage import container_client
-from tempest.services.object_storage import object_client
-from tempest.services.orchestration.json import orchestration_client
-from tempest.services.telemetry.json import alarming_client
-from tempest.services.telemetry.json import telemetry_client
-from tempest.services.volume.v1.json.admin import hosts_client \
- as volume_hosts_client
-from tempest.services.volume.v1.json.admin import quotas_client \
- as volume_quotas_client
-from tempest.services.volume.v1.json.admin import services_client \
- as volume_services_client
-from tempest.services.volume.v1.json.admin import types_client \
- as volume_types_client
-from tempest.services.volume.v1.json import availability_zone_client \
- as volume_az_client
-from tempest.services.volume.v1.json import backups_client
-from tempest.services.volume.v1.json import extensions_client \
- as volume_extensions_client
-from tempest.services.volume.v1.json import qos_client
-from tempest.services.volume.v1.json import snapshots_client
-from tempest.services.volume.v1.json import volumes_client
-from tempest.services.volume.v2.json.admin import hosts_client \
- as volume_v2_hosts_client
-from tempest.services.volume.v2.json.admin import quotas_client \
- as volume_v2_quotas_client
-from tempest.services.volume.v2.json.admin import services_client \
- as volume_v2_services_client
-from tempest.services.volume.v2.json.admin import types_client \
- as volume_v2_types_client
-from tempest.services.volume.v2.json import availability_zone_client \
- as volume_v2_az_client
-from tempest.services.volume.v2.json import backups_client \
- as volume_v2_backups_client
-from tempest.services.volume.v2.json import extensions_client \
- as volume_v2_extensions_client
-from tempest.services.volume.v2.json import qos_client as volume_v2_qos_client
-from tempest.services.volume.v2.json import snapshots_client \
- as volume_v2_snapshots_client
-from tempest.services.volume.v2.json import volumes_client as \
- volume_v2_volumes_client
-from tempest.tests import base
-
-
-class TestServiceClient(base.TestCase):
-
- @mock.patch('tempest.lib.common.rest_client.RestClient.__init__')
- def test_service_client_creations_with_specified_args(self, mock_init):
- test_clients = [
- baremetal_client.BaremetalClient,
- data_processing_client.DataProcessingClient,
- db_flavor_client.DatabaseFlavorsClient,
- db_version_client.DatabaseVersionsClient,
- network_client.NetworkClient,
- account_client.AccountClient,
- container_client.ContainerClient,
- object_client.ObjectClient,
- orchestration_client.OrchestrationClient,
- telemetry_client.TelemetryClient,
- alarming_client.AlarmingClient,
- qos_client.QosSpecsClient,
- volume_hosts_client.HostsClient,
- volume_quotas_client.QuotasClient,
- volume_services_client.ServicesClient,
- volume_types_client.TypesClient,
- volume_az_client.AvailabilityZoneClient,
- backups_client.BackupsClient,
- volume_extensions_client.ExtensionsClient,
- snapshots_client.SnapshotsClient,
- volumes_client.VolumesClient,
- volume_v2_hosts_client.HostsClient,
- volume_v2_quotas_client.QuotasClient,
- volume_v2_services_client.ServicesClient,
- volume_v2_types_client.TypesClient,
- volume_v2_az_client.AvailabilityZoneClient,
- volume_v2_backups_client.BackupsClient,
- volume_v2_extensions_client.ExtensionsClient,
- volume_v2_qos_client.QosSpecsClient,
- volume_v2_snapshots_client.SnapshotsClient,
- volume_v2_volumes_client.VolumesClient,
- identity_v2_identity_client.IdentityClient,
- credentials_client.CredentialsClient,
- endpoints_client.EndPointClient,
- identity_v3_identity_client.IdentityV3Client,
- policies_client.PoliciesClient,
- regions_client.RegionsClient,
- services_client.ServicesClient,
- images_client.ImagesClient,
- images_v2_client.ImagesClientV2
- ]
-
- for client in test_clients:
- fake_string = six.text_type(random.randint(1, 0x7fffffff))
- auth = 'auth' + fake_string
- service = 'service' + fake_string
- region = 'region' + fake_string
- params = {
- 'endpoint_type': 'URL' + fake_string,
- 'build_interval': random.randint(1, 100),
- 'build_timeout': random.randint(1, 100),
- 'disable_ssl_certificate_validation':
- True if random.randint(0, 1) else False,
- 'ca_certs': None,
- 'trace_requests': 'foo' + fake_string
- }
- client(auth, service, region, **params)
- mock_init.assert_called_once_with(auth, service, region, **params)
- mock_init.reset_mock()
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index c7cc638..492bdca 100644
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -20,6 +20,7 @@
from tempest import exceptions
from tempest.services.volume.base import base_volumes_client
from tempest.tests import base
+import tempest.tests.utils as utils
class TestImageWaiters(base.TestCase):
@@ -37,17 +38,24 @@
# Ensure waiter returns before build_timeout
self.assertTrue((end_time - start_time) < 10)
- def test_wait_for_image_status_timeout(self):
+ @mock.patch('time.sleep')
+ def test_wait_for_image_status_timeout(self, mock_sleep):
+ time_mock = self.patch('time.time')
+ time_mock.side_effect = utils.generate_timeout_series(1)
+
self.client.show_image.return_value = ({'status': 'saving'})
self.assertRaises(exceptions.TimeoutException,
waiters.wait_for_image_status,
self.client, 'fake_image_id', 'active')
+ mock_sleep.assert_called_once_with(1)
- def test_wait_for_image_status_error_on_image_create(self):
+ @mock.patch('time.sleep')
+ def test_wait_for_image_status_error_on_image_create(self, mock_sleep):
self.client.show_image.return_value = ({'status': 'ERROR'})
self.assertRaises(exceptions.AddImageException,
waiters.wait_for_image_status,
self.client, 'fake_image_id', 'active')
+ mock_sleep.assert_called_once_with(1)
@mock.patch.object(time, 'sleep')
def test_wait_for_volume_status_error_restoring(self, mock_sleep):
diff --git a/tempest/tests/common/test_api_version_request.py b/tempest/tests/lib/common/test_api_version_request.py
similarity index 97%
rename from tempest/tests/common/test_api_version_request.py
rename to tempest/tests/lib/common/test_api_version_request.py
index 38fbfc1..bdaa936 100644
--- a/tempest/tests/common/test_api_version_request.py
+++ b/tempest/tests/lib/common/test_api_version_request.py
@@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common import api_version_request
-from tempest import exceptions
-from tempest.tests import base
+from tempest.lib.common import api_version_request
+from tempest.lib import exceptions
+from tempest.tests.lib import base
class APIVersionRequestTests(base.TestCase):
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/lib/common/test_api_version_utils.py
similarity index 97%
rename from tempest/tests/common/test_api_version_utils.py
rename to tempest/tests/lib/common/test_api_version_utils.py
index 501f954..591b87e 100644
--- a/tempest/tests/common/test_api_version_utils.py
+++ b/tempest/tests/lib/common/test_api_version_utils.py
@@ -14,9 +14,9 @@
import testtools
-from tempest.common import api_version_utils
-from tempest import exceptions
-from tempest.tests import base
+from tempest.lib.common import api_version_utils
+from tempest.lib import exceptions
+from tempest.tests.lib import base
class TestVersionSkipLogic(base.TestCase):
diff --git a/tempest/tests/lib/common/utils/test_data_utils.py b/tempest/tests/lib/common/utils/test_data_utils.py
index 07502d0..493df89 100644
--- a/tempest/tests/lib/common/utils/test_data_utils.py
+++ b/tempest/tests/lib/common/utils/test_data_utils.py
@@ -24,15 +24,15 @@
def test_rand_uuid(self):
actual = data_utils.rand_uuid()
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]"
- "{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
+ self.assertRegex(actual, "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]"
+ "{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
actual2 = data_utils.rand_uuid()
self.assertNotEqual(actual, actual2)
def test_rand_uuid_hex(self):
actual = data_utils.rand_uuid_hex()
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^[0-9a-f]{32}$")
+ self.assertRegex(actual, "^[0-9a-f]{32}$")
actual2 = data_utils.rand_uuid_hex()
self.assertNotEqual(actual, actual2)
@@ -52,14 +52,14 @@
def test_rand_name_with_prefix(self):
actual = data_utils.rand_name(prefix='prefix-str')
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^prefix-str-")
+ self.assertRegex(actual, "^prefix-str-")
actual2 = data_utils.rand_name(prefix='prefix-str')
self.assertNotEqual(actual, actual2)
def test_rand_password(self):
actual = data_utils.rand_password()
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "[A-Za-z0-9~!@#$%^&*_=+]{15,}")
+ self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{15,}")
actual2 = data_utils.rand_password()
self.assertNotEqual(actual, actual2)
@@ -67,7 +67,7 @@
actual = data_utils.rand_password(8)
self.assertIsInstance(actual, str)
self.assertEqual(len(actual), 8)
- self.assertRegexpMatches(actual, "[A-Za-z0-9~!@#$%^&*_=+]{8}")
+ self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{8}")
actual2 = data_utils.rand_password(8)
self.assertNotEqual(actual, actual2)
@@ -75,14 +75,14 @@
actual = data_utils.rand_password(2)
self.assertIsInstance(actual, str)
self.assertEqual(len(actual), 3)
- self.assertRegexpMatches(actual, "[A-Za-z0-9~!@#$%^&*_=+]{3}")
+ self.assertRegex(actual, "[A-Za-z0-9~!@#$%^&*_=+]{3}")
actual2 = data_utils.rand_password(2)
self.assertNotEqual(actual, actual2)
def test_rand_url(self):
actual = data_utils.rand_url()
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^https://url-[0-9]*\.com$")
+ self.assertRegex(actual, "^https://url-[0-9]*\.com$")
actual2 = data_utils.rand_url()
self.assertNotEqual(actual, actual2)
@@ -96,8 +96,8 @@
def test_rand_mac_address(self):
actual = data_utils.rand_mac_address()
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^([0-9a-f][0-9a-f]:){5}"
- "[0-9a-f][0-9a-f]$")
+ self.assertRegex(actual, "^([0-9a-f][0-9a-f]:){5}"
+ "[0-9a-f][0-9a-f]$")
actual2 = data_utils.rand_mac_address()
self.assertNotEqual(actual, actual2)
@@ -117,12 +117,12 @@
def test_random_bytes(self):
actual = data_utils.random_bytes() # default size=1024
self.assertIsInstance(actual, str)
- self.assertRegexpMatches(actual, "^[\x00-\xFF]{1024}")
+ self.assertRegex(actual, "^[\x00-\xFF]{1024}")
actual2 = data_utils.random_bytes()
self.assertNotEqual(actual, actual2)
actual = data_utils.random_bytes(size=2048)
- self.assertRegexpMatches(actual, "^[\x00-\xFF]{2048}")
+ self.assertRegex(actual, "^[\x00-\xFF]{2048}")
def test_get_ipv6_addr_by_EUI64(self):
actual = data_utils.get_ipv6_addr_by_EUI64('2001:db8::',
diff --git a/tempest/tests/lib/fake_auth_provider.py b/tempest/tests/lib/fake_auth_provider.py
index 7f00fb8..8095453 100644
--- a/tempest/tests/lib/fake_auth_provider.py
+++ b/tempest/tests/lib/fake_auth_provider.py
@@ -16,15 +16,16 @@
class FakeAuthProvider(object):
- def __init__(self, creds_dict=None):
+ def __init__(self, creds_dict=None, fake_base_url=None):
creds_dict = creds_dict or {}
self.credentials = FakeCredentials(creds_dict)
+ self.fake_base_url = fake_base_url
def auth_request(self, method, url, headers=None, body=None, filters=None):
return url, headers, body
def base_url(self, filters, auth_data=None):
- return "https://example.com"
+ return self.fake_base_url or "https://example.com"
class FakeCredentials(object):
diff --git a/tempest/tests/services/compute/test_base_compute_client.py b/tempest/tests/lib/services/compute/test_base_compute_client.py
similarity index 86%
rename from tempest/tests/services/compute/test_base_compute_client.py
rename to tempest/tests/lib/services/compute/test_base_compute_client.py
index 1a78247..f552ef5 100644
--- a/tempest/tests/services/compute/test_base_compute_client.py
+++ b/tempest/tests/lib/services/compute/test_base_compute_client.py
@@ -16,12 +16,11 @@
import mock
from oslotest import mockpatch
-from tempest.api.compute import api_microversion_fixture
-from tempest import exceptions
from tempest.lib.common import rest_client
-from tempest.services.compute.json import base_compute_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
+from tempest.lib import exceptions
+from tempest.lib.services.compute import base_compute_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services.compute import base
class TestMicroversionHeaderCheck(base.BaseComputeServiceTest):
@@ -31,7 +30,11 @@
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = base_compute_client.BaseComputeClient(
fake_auth, 'compute', 'regionOne')
- self.useFixture(api_microversion_fixture.APIMicroversionFixture('2.2'))
+ base_compute_client.COMPUTE_MICROVERSION = '2.2'
+
+ def tearDown(self):
+ super(TestMicroversionHeaderCheck, self).tearDown()
+ base_compute_client.COMPUTE_MICROVERSION = None
def _check_microverion_header_in_response(self, fake_response):
def request(*args, **kwargs):
@@ -77,8 +80,11 @@
super(TestSchemaVersionsNone, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = DummyServiceClient1(fake_auth, 'compute', 'regionOne')
- self.useFixture(api_microversion_fixture.APIMicroversionFixture(
- self.api_microversion))
+ base_compute_client.COMPUTE_MICROVERSION = self.api_microversion
+
+ def tearDown(self):
+ super(TestSchemaVersionsNone, self).tearDown()
+ base_compute_client.COMPUTE_MICROVERSION = None
def test_schema(self):
self.assertEqual(self.expected_schema,
@@ -132,8 +138,11 @@
super(TestSchemaVersionsNotFound, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = DummyServiceClient2(fake_auth, 'compute', 'regionOne')
- self.useFixture(api_microversion_fixture.APIMicroversionFixture(
- self.api_microversion))
+ base_compute_client.COMPUTE_MICROVERSION = self.api_microversion
+
+ def tearDown(self):
+ super(TestSchemaVersionsNotFound, self).tearDown()
+ base_compute_client.COMPUTE_MICROVERSION = None
def test_schema(self):
self.assertRaises(exceptions.JSONSchemaNotFound,
@@ -170,7 +179,11 @@
fake_auth = fake_auth_provider.FakeAuthProvider()
self.client = base_compute_client.BaseComputeClient(
fake_auth, 'compute', 'regionOne')
- self.useFixture(api_microversion_fixture.APIMicroversionFixture('2.2'))
+ base_compute_client.COMPUTE_MICROVERSION = '2.2'
+
+ def tearDown(self):
+ super(TestClientWithMicroversionHeader, self).tearDown()
+ base_compute_client.COMPUTE_MICROVERSION = None
def test_microverion_header(self):
header = self.client.get_headers()
diff --git a/tempest/tests/lib/services/compute/test_versions_client.py b/tempest/tests/lib/services/compute/test_versions_client.py
index 5ac2f2d..fc6c1d2 100644
--- a/tempest/tests/lib/services/compute/test_versions_client.py
+++ b/tempest/tests/lib/services/compute/test_versions_client.py
@@ -94,3 +94,42 @@
def test_get_version_by_url_with_bytes_body(self):
self._test_get_version_by_url(bytes_body=True)
+
+ def _test_get_base_version_url(self, url, expected_base_url):
+ auth = fake_auth_provider.FakeAuthProvider(fake_base_url=url)
+ client = versions_client.VersionsClient(auth, 'compute', 'regionOne')
+ self.assertEqual(expected_base_url, client._get_base_version_url())
+
+ def test_get_base_version_url(self):
+ self._test_get_base_version_url('https://bar.org/v2/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org/v2.1/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org/v2.15/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org/v22.2/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org/v22/123',
+ 'https://bar.org/')
+
+ def test_get_base_version_url_app_name(self):
+ self._test_get_base_version_url('https://bar.org/compute/v2/123',
+ 'https://bar.org/compute/')
+ self._test_get_base_version_url('https://bar.org/compute/v2.1/123',
+ 'https://bar.org/compute/')
+ self._test_get_base_version_url('https://bar.org/compute/v2.15/123',
+ 'https://bar.org/compute/')
+ self._test_get_base_version_url('https://bar.org/compute/v22.2/123',
+ 'https://bar.org/compute/')
+ self._test_get_base_version_url('https://bar.org/compute/v22/123',
+ 'https://bar.org/compute/')
+
+ def test_get_base_version_url_double_slash(self):
+ self._test_get_base_version_url('https://bar.org//v2/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org//v2.1/123',
+ 'https://bar.org/')
+ self._test_get_base_version_url('https://bar.org/compute//v2/123',
+ 'https://bar.org/compute/')
+ self._test_get_base_version_url('https://bar.org/compute//v2.1/123',
+ 'https://bar.org/compute/')
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index f7bc7e4..6a01490 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -382,6 +382,31 @@
expected = 'http://fake_url/'
self._test_base_url_helper(expected, self.filters)
+ def test_base_url_with_unversioned_endpoint(self):
+ auth_data = {
+ 'serviceCatalog': [
+ {
+ 'type': 'identity',
+ 'endpoints': [
+ {
+ 'region': 'FakeRegion',
+ 'publicURL': 'http://fake_url'
+ }
+ ]
+ }
+ ]
+ }
+
+ filters = {
+ 'service': 'identity',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion',
+ 'api_version': 'v2.0'
+ }
+
+ expected = 'http://fake_url/v2.0'
+ self._test_base_url_helper(expected, filters, ('token', auth_data))
+
def test_token_not_expired(self):
expiry_data = datetime.datetime.utcnow() + datetime.timedelta(days=1)
self._verify_expiry(expiry_data=expiry_data, should_be_expired=False)
@@ -478,3 +503,70 @@
expected = self._get_result_url_from_endpoint(
self._endpoints[0]['endpoints'][2])
self._test_base_url_helper(expected, self.filters)
+
+ # Overwrites v2 test
+ def test_base_url_with_unversioned_endpoint(self):
+ auth_data = {
+ 'catalog': [
+ {
+ 'type': 'identity',
+ 'endpoints': [
+ {
+ 'region': 'FakeRegion',
+ 'url': 'http://fake_url',
+ 'interface': 'public'
+ }
+ ]
+ }
+ ]
+ }
+
+ filters = {
+ 'service': 'identity',
+ 'endpoint_type': 'publicURL',
+ 'region': 'FakeRegion',
+ 'api_version': 'v3'
+ }
+
+ expected = 'http://fake_url/v3'
+ self._test_base_url_helper(expected, filters, ('token', auth_data))
+
+
+class TestKeystoneV3Credentials(base.TestCase):
+ def testSetAttrUserDomain(self):
+ creds = auth.KeystoneV3Credentials()
+ creds.user_domain_name = 'user_domain'
+ creds.domain_name = 'domain'
+ self.assertEqual('user_domain', creds.user_domain_name)
+ creds = auth.KeystoneV3Credentials()
+ creds.domain_name = 'domain'
+ creds.user_domain_name = 'user_domain'
+ self.assertEqual('user_domain', creds.user_domain_name)
+
+ def testSetAttrProjectDomain(self):
+ creds = auth.KeystoneV3Credentials()
+ creds.project_domain_name = 'project_domain'
+ creds.domain_name = 'domain'
+ self.assertEqual('project_domain', creds.user_domain_name)
+ creds = auth.KeystoneV3Credentials()
+ creds.domain_name = 'domain'
+ creds.project_domain_name = 'project_domain'
+ self.assertEqual('project_domain', creds.project_domain_name)
+
+ def testProjectTenantNoCollision(self):
+ creds = auth.KeystoneV3Credentials(tenant_id='tenant')
+ self.assertEqual('tenant', creds.project_id)
+ creds = auth.KeystoneV3Credentials(project_id='project')
+ self.assertEqual('project', creds.tenant_id)
+ creds = auth.KeystoneV3Credentials(tenant_name='tenant')
+ self.assertEqual('tenant', creds.project_name)
+ creds = auth.KeystoneV3Credentials(project_name='project')
+ self.assertEqual('project', creds.tenant_name)
+
+ def testProjectTenantCollision(self):
+ attrs = {'tenant_id': 'tenant', 'project_id': 'project'}
+ self.assertRaises(
+ exceptions.InvalidCredentials, auth.KeystoneV3Credentials, **attrs)
+ attrs = {'tenant_name': 'tenant', 'project_name': 'project'}
+ self.assertRaises(
+ exceptions.InvalidCredentials, auth.KeystoneV3Credentials, **attrs)
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index 558445d..07b577c 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -109,7 +109,7 @@
t = TestFoo('test_foo')
if expected_to_skip:
self.assertRaises(testtools.TestCase.skipException,
- t.test_foo())
+ t.test_foo)
else:
try:
t.test_foo()
diff --git a/tempest/tests/lib/test_rest_client.py b/tempest/tests/lib/test_rest_client.py
index 6aff305..87af455 100644
--- a/tempest/tests/lib/test_rest_client.py
+++ b/tempest/tests/lib/test_rest_client.py
@@ -25,6 +25,7 @@
from tempest.tests.lib import base
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib import fake_http
+import tempest.tests.utils as utils
class BaseRestClientTestClass(base.TestCase):
@@ -511,11 +512,20 @@
def test_wait_for_resource_deletion_not_deleted(self):
self.patch('time.sleep')
# Set timeout to be very quick to force exception faster
- self.rest_client.build_timeout = 1
+ timeout = 1
+ self.rest_client.build_timeout = timeout
+
+ time_mock = self.patch('time.time')
+ time_mock.side_effect = utils.generate_timeout_series(timeout)
+
self.assertRaises(exceptions.TimeoutException,
self.rest_client.wait_for_resource_deletion,
'1234')
+ # time.time() should be called twice, first to start the timer
+ # and then to compute the timedelta
+ self.assertEqual(2, time_mock.call_count)
+
def test_wait_for_deletion_with_unimplemented_deleted_method(self):
self.rest_client.is_resource_deleted = self.original_deleted_method
self.assertRaises(NotImplementedError,
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index 7a4fc09..f6efd47 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -14,7 +14,6 @@
from io import StringIO
import socket
-import time
import mock
import six
@@ -23,6 +22,7 @@
from tempest.lib.common import ssh
from tempest.lib import exceptions
from tempest.tests.lib import base
+import tempest.tests.utils as utils
class TestSshClient(base.TestCase):
@@ -79,7 +79,8 @@
self.assertEqual(expected_connect, client_mock.connect.mock_calls)
self.assertEqual(0, s_mock.call_count)
- def test_get_ssh_connection_two_attemps(self):
+ @mock.patch('time.sleep')
+ def test_get_ssh_connection_two_attemps(self, sleep_mock):
c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
c_mock.return_value = client_mock
@@ -89,15 +90,18 @@
]
client = ssh.Client('localhost', 'root', timeout=1)
- start_time = int(time.time())
client._get_ssh_connection(sleep=1)
- end_time = int(time.time())
- self.assertLess((end_time - start_time), 4)
- self.assertGreater((end_time - start_time), 1)
+ # We slept 2 seconds: because sleep is "1" and backoff is "1" too
+ sleep_mock.assert_called_once_with(2)
+ self.assertEqual(2, client_mock.connect.call_count)
def test_get_ssh_connection_timeout(self):
c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
+ timeout = 2
+ time_mock = self.patch('time.time')
+ time_mock.side_effect = utils.generate_timeout_series(timeout + 1)
+
c_mock.return_value = client_mock
client_mock.connect.side_effect = [
socket.error,
@@ -105,13 +109,16 @@
socket.error,
]
- client = ssh.Client('localhost', 'root', timeout=2)
- start_time = int(time.time())
- with testtools.ExpectedException(exceptions.SSHTimeout):
- client._get_ssh_connection()
- end_time = int(time.time())
- self.assertLess((end_time - start_time), 5)
- self.assertGreaterEqual((end_time - start_time), 2)
+ client = ssh.Client('localhost', 'root', timeout=timeout)
+ # We need to mock LOG here because LOG.info() calls time.time()
+ # in order to preprend a timestamp.
+ with mock.patch.object(ssh, 'LOG'):
+ self.assertRaises(exceptions.SSHTimeout,
+ client._get_ssh_connection)
+
+ # time.time() should be called twice, first to start the timer
+ # and then to compute the timedelta
+ self.assertEqual(2, time_mock.call_count)
@mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
def test_timeout_in_exec_command(self):
diff --git a/tempest/tests/test_microversions.py b/tempest/tests/test_microversions.py
index 6738641..cef7975 100644
--- a/tempest/tests/test_microversions.py
+++ b/tempest/tests/test_microversions.py
@@ -17,7 +17,7 @@
from tempest.api.compute import base as compute_base
from tempest import config
-from tempest import exceptions
+from tempest.lib import exceptions
from tempest.tests import base
from tempest.tests import fake_config
@@ -64,9 +64,9 @@
expected_pass_tests,
expected_skip_tests):
cfg.CONF.set_default('min_microversion',
- cfg_min, group='compute-feature-enabled')
+ cfg_min, group='compute')
cfg.CONF.set_default('max_microversion',
- cfg_max, group='compute-feature-enabled')
+ cfg_max, group='compute')
try:
for test_class in expected_pass_tests:
test_class.skip_checks()
@@ -138,16 +138,16 @@
def test_config_invalid_version(self):
cfg.CONF.set_default('min_microversion',
- '2.5', group='compute-feature-enabled')
+ '2.5', group='compute')
cfg.CONF.set_default('max_microversion',
- '2.1', group='compute-feature-enabled')
+ '2.1', group='compute')
self.assertRaises(exceptions.InvalidAPIVersionRange,
VersionTestNoneTolatest.skip_checks)
def test_config_version_invalid_test_version(self):
cfg.CONF.set_default('min_microversion',
- None, group='compute-feature-enabled')
+ None, group='compute')
cfg.CONF.set_default('max_microversion',
- '2.13', group='compute-feature-enabled')
+ '2.13', group='compute')
self.assertRaises(exceptions.InvalidAPIVersionRange,
InvalidVersionTest.skip_checks)
diff --git a/tempest/tests/utils.py b/tempest/tests/utils.py
new file mode 100644
index 0000000..9c3049d
--- /dev/null
+++ b/tempest/tests/utils.py
@@ -0,0 +1,29 @@
+# Copyright 2016 OpenStack Foundation
+#
+# 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.
+#
+
+
+def generate_timeout_series(timeout):
+ """Generate a series of times that exceeds the given timeout.
+
+ Yields a series of fake time.time() floating point numbers
+ such that the difference between each pair in the series just
+ exceeds the timeout value that is passed in. Useful for
+ mocking time.time() in methods that otherwise wait for timeout
+ seconds.
+ """
+ iteration = 0
+ while True:
+ iteration += 1
+ yield (iteration * timeout) + iteration
diff --git a/test-requirements.txt b/test-requirements.txt
index a92adb0..be3a4f1 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -6,7 +6,7 @@
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2 # BSD
python-subunit>=0.0.18 # Apache-2.0/BSD
oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0
-reno>=0.1.1 # Apache2
+reno>=0.1.1 # Apache2
mox>=0.5.3 # Apache-2.0
mock>=1.2 # BSD
coverage>=3.6 # Apache-2.0
diff --git a/tools/skip_tracker.py b/tools/skip_tracker.py
index a47e217..b554514 100755
--- a/tools/skip_tracker.py
+++ b/tools/skip_tracker.py
@@ -73,21 +73,23 @@
DEF_RE = re.compile(r'\s*def (\w+)\(')
bug_found = False
results = []
- lines = open(path, 'rb').readlines()
- for x, line in enumerate(lines):
- if not bug_found:
- res = BUG_RE.match(line)
- if res:
- bug_no = int(res.group(1))
- debug("Found bug skip %s on line %d", bug_no, x + 1)
- bug_found = True
- else:
- res = DEF_RE.match(line)
- if res:
- method = res.group(1)
- debug("Found test method %s skips for bug %d", method, bug_no)
- results.append((method, bug_no))
- bug_found = False
+ with open(path, 'rb') as content:
+ lines = content.readlines()
+ for x, line in enumerate(lines):
+ if not bug_found:
+ res = BUG_RE.match(line)
+ if res:
+ bug_no = int(res.group(1))
+ debug("Found bug skip %s on line %d", bug_no, x + 1)
+ bug_found = True
+ else:
+ res = DEF_RE.match(line)
+ if res:
+ method = res.group(1)
+ debug("Found test method %s skips for bug %d",
+ method, bug_no)
+ results.append((method, bug_no))
+ bug_found = False
return results
diff --git a/tox.ini b/tox.ini
index 96a97f4..28dfe8b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -70,14 +70,6 @@
find . -type f -name "*.pyc" -delete
bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
-[testenv:large-ops]
-sitepackages = {[tempestenv]sitepackages}
-setenv = {[tempestenv]setenv}
-deps = {[tempestenv]deps}
-commands =
- find . -type f -name "*.pyc" -delete
- python setup.py testr --slowest --testr-args='tempest.scenario.test_large_ops {posargs}'
-
[testenv:smoke]
sitepackages = {[tempestenv]sitepackages}
setenv = {[tempestenv]setenv}