Merge "Fix skip_checks in live_migration"
diff --git a/README.rst b/README.rst
index bf513bd..45cb4c0 100644
--- a/README.rst
+++ b/README.rst
@@ -22,8 +22,8 @@
- Tempest should not touch private or implementation specific
interfaces. This means not directly going to the database, not
directly hitting the hypervisors, not testing extensions not
- included in the OpenStack base. If there is some feature of
- OpenStack that is not verifiable through standard interfaces, this
+ included in the OpenStack base. If there are some features of
+ OpenStack that are not verifiable through standard interfaces, this
should be considered a possible enhancement.
- Tempest strives for complete coverage of the OpenStack API and
common scenarios that demonstrate a working cloud.
@@ -47,10 +47,11 @@
assumptions related to that. For this section we'll only cover the newer method
as it is simpler, and quicker to work with.
-#. You first need to install Tempest this is done with pip, after you check out
- the Tempest repo you simply run something like::
+#. You first need to install Tempest. This is done with pip after you check out
+ the Tempest repo::
- $ pip install tempest
+ $ git clone https://github.com/openstack/tempest/
+ $ pip install tempest/
This can be done within a venv, but the assumption for this guide is that
the Tempest cli entry point will be in your shell's PATH.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 02fa0d8..1b2b6d2 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -127,16 +127,16 @@
unexpected failures in some tests.
-Non-locking test accounts (aka credentials config options)
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+Legacy test accounts (aka credentials config options)
+"""""""""""""""""""""""""""""""""""""""""""""""""""""
**Starting in the Liberty release this mechanism was deprecated and will be
removed in a future release**
When Tempest was refactored to allow for locking test accounts, the original
non-tenant isolated case was converted to internally work similarly to the
-accounts.yaml file. This mechanism was then called the non-locking test accounts
-provider. To use the non-locking test accounts provider you can specify the sets
-of credentials in the configuration file like detailed above with following 9
+accounts.yaml file. This mechanism was then called the legacy test accounts
+provider. To use the legacy test accounts provider you can specify the sets of
+credentials in the configuration file like detailed above with following 9
options in the identity section:
#. username
diff --git a/doc/source/plugin.rst b/doc/source/plugin.rst
index a41038c..29653a6 100644
--- a/doc/source/plugin.rst
+++ b/doc/source/plugin.rst
@@ -26,7 +26,7 @@
In order to create the basic structure with base classes and test directories
you can use the tempest-plugin-cookiecutter project::
- > cookiecutter https://git.openstack.org/openstack/tempest-plugin-cookiecutter
+ > pip install -U cookiecutter && cookiecutter https://git.openstack.org/openstack/tempest-plugin-cookiecutter
Cloning into 'tempest-plugin-cookiecutter'...
remote: Counting objects: 17, done.
diff --git a/requirements.txt b/requirements.txt
index 59d6856..370bb65 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -15,7 +15,7 @@
oslo.concurrency>=2.3.0 # Apache-2.0
oslo.config>=2.6.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
-oslo.log>=1.8.0 # Apache-2.0
+oslo.log>=1.12.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils!=2.6.0,>=2.4.0 # Apache-2.0
six>=1.9.0
diff --git a/tempest/api/baremetal/admin/base.py b/tempest/api/baremetal/admin/base.py
index d7d2efe..80b69b9 100644
--- a/tempest/api/baremetal/admin/base.py
+++ b/tempest/api/baremetal/admin/base.py
@@ -98,8 +98,7 @@
@classmethod
@creates('chassis')
def create_chassis(cls, description=None, expect_errors=False):
- """
- Wrapper utility for creating test chassis.
+ """Wrapper utility for creating test chassis.
:param description: A description of the chassis. if not supplied,
a random value will be generated.
@@ -114,8 +113,7 @@
@creates('node')
def create_node(cls, chassis_id, cpu_arch='x86', cpus=8, local_gb=10,
memory_mb=4096):
- """
- Wrapper utility for creating test baremetal nodes.
+ """Wrapper utility for creating test baremetal nodes.
:param cpu_arch: CPU architecture of the node. Default: x86.
:param cpus: Number of CPUs. Default: 8.
@@ -134,8 +132,7 @@
@classmethod
@creates('port')
def create_port(cls, node_id, address, extra=None, uuid=None):
- """
- Wrapper utility for creating test ports.
+ """Wrapper utility for creating test ports.
:param address: MAC address of the port.
:param extra: Meta data of the port. If not supplied, an empty
@@ -152,8 +149,7 @@
@classmethod
def delete_chassis(cls, chassis_id):
- """
- Deletes a chassis having the specified UUID.
+ """Deletes a chassis having the specified UUID.
:param uuid: The unique identifier of the chassis.
:return: Server response.
@@ -169,8 +165,7 @@
@classmethod
def delete_node(cls, node_id):
- """
- Deletes a node having the specified UUID.
+ """Deletes a node having the specified UUID.
:param uuid: The unique identifier of the node.
:return: Server response.
@@ -186,8 +181,7 @@
@classmethod
def delete_port(cls, port_id):
- """
- Deletes a port having the specified UUID.
+ """Deletes a port having the specified UUID.
:param uuid: The unique identifier of the port.
:return: Server response.
diff --git a/tempest/api/compute/admin/test_baremetal_nodes.py b/tempest/api/compute/admin/test_baremetal_nodes.py
index 2599d86..b764483 100644
--- a/tempest/api/compute/admin/test_baremetal_nodes.py
+++ b/tempest/api/compute/admin/test_baremetal_nodes.py
@@ -20,9 +20,7 @@
class BaremetalNodesAdminTestJSON(base.BaseV2ComputeAdminTest):
- """
- Tests Baremetal API
- """
+ """Tests Baremetal API"""
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index dfaa5d5..993d39e 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -22,10 +22,7 @@
class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
-
- """
- Tests Servers API using admin privileges
- """
+ """Tests Servers API using admin privileges"""
_host_key = 'OS-EXT-SRV-ATTR:host'
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index 0c81ccb..e57401a 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -19,10 +19,7 @@
class ServicesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
-
- """
- Tests Services API. List and Enable/Disable require admin privileges.
- """
+ """Tests Services API. List and Enable/Disable require admin privileges."""
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index 5d78539..4e88f65 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -399,6 +399,7 @@
@classmethod
def _get_default_version(cls):
"""Returns the default plugin version used for testing.
+
This is gathered separately from the plugin to allow
the usage of plugin name in skip_checks. This method is
rather invoked into resource_setup, which allows API calls
@@ -439,6 +440,7 @@
@classmethod
def get_cluster_template(cls, node_group_template_ids=None):
"""Returns a cluster template for the default plugin.
+
node_group_template_defined contains the type and ID of pre-defined
node group templates that have to be used in the cluster template
(instead of dynamically defining them with 'node_processes').
diff --git a/tempest/api/data_processing/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
index 42cbd14..dfd8e27 100644
--- a/tempest/api/data_processing/test_cluster_templates.py
+++ b/tempest/api/data_processing/test_cluster_templates.py
@@ -19,9 +19,9 @@
class ClusterTemplateTest(dp_base.BaseDataProcessingTest):
- """Link to the API documentation is http://docs.openstack.org/developer/
- sahara/restapi/rest_api_v1.0.html#cluster-templates
- """
+ # Link to the API documentation is http://docs.openstack.org/developer/
+ # sahara/restapi/rest_api_v1.0.html#cluster-templates
+
@classmethod
def skip_checks(cls):
super(ClusterTemplateTest, cls).skip_checks()
diff --git a/tempest/api/data_processing/test_job_binaries.py b/tempest/api/data_processing/test_job_binaries.py
index 98b7e24..a47ddbc 100644
--- a/tempest/api/data_processing/test_job_binaries.py
+++ b/tempest/api/data_processing/test_job_binaries.py
@@ -18,9 +18,9 @@
class JobBinaryTest(dp_base.BaseDataProcessingTest):
- """Link to the API documentation is http://docs.openstack.org/developer/
- sahara/restapi/rest_api_v1.1_EDP.html#job-binaries
- """
+ # Link to the API documentation is http://docs.openstack.org/developer/
+ # sahara/restapi/rest_api_v1.1_EDP.html#job-binaries
+
@classmethod
def resource_setup(cls):
super(JobBinaryTest, cls).resource_setup()
diff --git a/tempest/api/data_processing/test_job_binary_internals.py b/tempest/api/data_processing/test_job_binary_internals.py
index 6919fa5..b4f0769 100644
--- a/tempest/api/data_processing/test_job_binary_internals.py
+++ b/tempest/api/data_processing/test_job_binary_internals.py
@@ -18,9 +18,9 @@
class JobBinaryInternalTest(dp_base.BaseDataProcessingTest):
- """Link to the API documentation is http://docs.openstack.org/developer/
- sahara/restapi/rest_api_v1.1_EDP.html#job-binary-internals
- """
+ # Link to the API documentation is http://docs.openstack.org/developer/
+ # sahara/restapi/rest_api_v1.1_EDP.html#job-binary-internals
+
@classmethod
def resource_setup(cls):
super(JobBinaryInternalTest, cls).resource_setup()
diff --git a/tempest/api/data_processing/test_jobs.py b/tempest/api/data_processing/test_jobs.py
index 7798056..8503320 100644
--- a/tempest/api/data_processing/test_jobs.py
+++ b/tempest/api/data_processing/test_jobs.py
@@ -18,9 +18,9 @@
class JobTest(dp_base.BaseDataProcessingTest):
- """Link to the API documentation is http://docs.openstack.org/developer/
- sahara/restapi/rest_api_v1.1_EDP.html#jobs
- """
+ # NOTE: Link to the API documentation: http://docs.openstack.org/developer/
+ # sahara/restapi/rest_api_v1.1_EDP.html#jobs
+
@classmethod
def resource_setup(cls):
super(JobTest, cls).resource_setup()
diff --git a/tempest/api/identity/admin/v2/test_tokens.py b/tempest/api/identity/admin/v2/test_tokens.py
index e808990..0e7a480 100644
--- a/tempest/api/identity/admin/v2/test_tokens.py
+++ b/tempest/api/identity/admin/v2/test_tokens.py
@@ -52,8 +52,9 @@
@test.idempotent_id('25ba82ee-8a32-4ceb-8f50-8b8c71e8765e')
def test_rescope_token(self):
- """An unscoped token can be requested, that token can be used to
- request a scoped token.
+ """An unscoped token can be requested
+
+ That token can be used to request a scoped token.
"""
# Create a user.
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 33819a8..9eb3149 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -44,3 +44,29 @@
# Domain name should not be empty
self.assertRaises(lib_exc.BadRequest, self.client.create_domain,
name='')
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('37b1bbf2-d664-4785-9a11-333438586eae')
+ def test_create_domain_with_name_length_over_64(self):
+ # Domain name length should not ne greater than 64 characters
+ d_name = 'a' * 65
+ self.assertRaises(lib_exc.BadRequest, self.client.create_domain,
+ d_name)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('43781c07-764f-4cf2-a405-953c1916f605')
+ def test_delete_non_existent_domain(self):
+ # Attempt to delete a non existent domain should fail
+ self.assertRaises(lib_exc.NotFound, self.client.delete_domain,
+ data_utils.rand_uuid_hex())
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('e6f9e4a2-4f36-4be8-bdbc-4e199ae29427')
+ def test_domain_create_duplicate(self):
+ domain_name = data_utils.rand_name('domain-dup')
+ domain = self.client.create_domain(domain_name)['domain']
+ domain_id = domain['id']
+ self.addCleanup(self.delete_domain, domain_id)
+ # Domain name should be unique
+ self.assertRaises(
+ lib_exc.Conflict, self.client.create_domain, domain_name)
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 2fd7369..429e2e3 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -33,9 +33,9 @@
s_name = data_utils.rand_name('service')
s_type = data_utils.rand_name('type')
s_description = data_utils.rand_name('description')
- cls.service_data =\
- cls.service_client.create_service(s_name, s_type,
- description=s_description)
+ cls.service_data = (
+ cls.service_client.create_service(name=s_name, type=s_type,
+ description=s_description))
cls.service_data = cls.service_data['service']
cls.service_id = cls.service_data['id']
cls.service_ids.append(cls.service_id)
@@ -112,9 +112,9 @@
s_name = data_utils.rand_name('service')
s_type = data_utils.rand_name('type')
s_description = data_utils.rand_name('description')
- service2 =\
- self.service_client.create_service(s_name, s_type,
- description=s_description)
+ service2 = (
+ self.service_client.create_service(name=s_name, type=s_type,
+ description=s_description))
service2 = service2['service']
self.service_ids.append(service2['id'])
# Updating endpoint with new values
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 5aa90a5..8f9bf2a 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -37,7 +37,7 @@
s_type = data_utils.rand_name('type')
s_description = data_utils.rand_name('description')
cls.service_data = (
- cls.service_client.create_service(s_name, s_type,
+ cls.service_client.create_service(name=s_name, type=s_type,
description=s_description)
['service'])
cls.service_id = cls.service_data['id']
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index dfb03df..d1595dd 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -37,7 +37,7 @@
serv_type = data_utils.rand_name('type')
desc = data_utils.rand_name('description')
create_service = self.service_client.create_service(
- serv_type, name=name, description=desc)['service']
+ type=serv_type, name=name, description=desc)['service']
self.addCleanup(self._del_service, create_service['id'])
self.assertIsNotNone(create_service['id'])
@@ -68,7 +68,7 @@
name = data_utils.rand_name('service')
serv_type = data_utils.rand_name('type')
service = self.service_client.create_service(
- serv_type, name=name)['service']
+ type=serv_type, name=name)['service']
self.addCleanup(self.service_client.delete_service, service['id'])
self.assertIn('id', service)
expected_data = {'name': name, 'type': serv_type}
@@ -82,7 +82,7 @@
name = data_utils.rand_name('service')
serv_type = data_utils.rand_name('type')
create_service = self.service_client.create_service(
- serv_type, name=name)['service']
+ type=serv_type, name=name)['service']
self.addCleanup(self.service_client.delete_service,
create_service['id'])
service_ids.append(create_service['id'])
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index fac8826..a8b0af9 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest import clients
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common.utils import data_utils
from tempest import config
from tempest import test
@@ -89,7 +89,7 @@
self.assertIsNotNone(self.trustee_user_id)
# Initialize a new client with the trustor credentials
- creds = cred_provider.get_credentials(
+ creds = common_creds.get_credentials(
identity_version='v3',
username=self.trustor_username,
password=self.trustor_password,
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 02ede3a..f9395bc 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -16,7 +16,7 @@
from oslo_log import log as logging
from tempest_lib import exceptions as lib_exc
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common.utils import data_utils
from tempest import config
import tempest.test
@@ -195,11 +195,11 @@
@property
def test_credentials(self):
- return cred_provider.get_credentials(username=self.test_user,
- user_id=self.user['id'],
- password=self.test_password,
- tenant_name=self.test_tenant,
- tenant_id=self.tenant['id'])
+ return common_creds.get_credentials(username=self.test_user,
+ user_id=self.user['id'],
+ password=self.test_password,
+ tenant_name=self.test_tenant,
+ tenant_id=self.tenant['id'])
def setup_test_user(self):
"""Set up a test user."""
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 3b89b66..50aaa25 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -14,6 +14,7 @@
# under the License.
import copy
+import time
from tempest_lib.common.utils import data_utils
from tempest_lib import exceptions
@@ -54,6 +55,15 @@
new_pass=old_pass,
old_pass=new_pass)
+ # TODO(lbragstad): Sleeping after the response status has been checked
+ # and the body loaded as JSON allows requests to fail-fast. The sleep
+ # is necessary because keystone will err on the side of security and
+ # invalidate tokens within a small margin of error (within the same
+ # wall clock second) after a revocation event is issued (such as a
+ # password change). Remove this once keystone and Fernet support
+ # sub-second precision.
+ time.sleep(1)
+
# user updates own password
resp = self.non_admin_client.update_user_own_password(
user_id=user_id, new_pass=new_pass, old_pass=old_pass)['access']
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index a1f664f..14a866f 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -14,6 +14,7 @@
# under the License.
import copy
+import time
from tempest_lib.common.utils import data_utils
from tempest_lib import exceptions
@@ -53,6 +54,15 @@
password=old_pass,
original_password=new_pass)
+ # TODO(lbragstad): Sleeping after the response status has been checked
+ # and the body loaded as JSON allows requests to fail-fast. The sleep
+ # is necessary because keystone will err on the side of security and
+ # invalidate tokens within a small margin of error (within the same
+ # wall clock second) after a revocation event is issued (such as a
+ # password change). Remove this once keystone and Fernet support
+ # sub-second precision.
+ time.sleep(1)
+
# user updates own password
self.non_admin_client.update_user_password(
user_id=user_id, password=new_pass, original_password=old_pass)
diff --git a/tempest/api/image/admin/v2/test_images.py b/tempest/api/image/admin/v2/test_images.py
index 09877ba..01838b6 100644
--- a/tempest/api/image/admin/v2/test_images.py
+++ b/tempest/api/image/admin/v2/test_images.py
@@ -26,10 +26,8 @@
class BasicAdminOperationsImagesTest(base.BaseV2ImageAdminTest):
+ """Here we test admin operations of images"""
- """
- Here we test admin operations of images
- """
@testtools.skipUnless(CONF.image_feature_enabled.deactivate_image,
'deactivate-image is not available.')
@test.idempotent_id('951ebe01-969f-4ea9-9898-8a3f1f442ab0')
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index d4dbfcd..64f3174 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -100,10 +100,7 @@
class ListImagesTest(base.BaseV1ImageTest):
-
- """
- Here we test the listing of image information
- """
+ """Here we test the listing of image information"""
@classmethod
def resource_setup(cls):
@@ -131,10 +128,8 @@
@classmethod
def _create_remote_image(cls, name, container_format, disk_format):
- """
- Create a new remote image and return the ID of the newly-registered
- image
- """
+ """Create a new remote image and return newly-registered image-id"""
+
name = 'New Remote Image %s' % name
location = CONF.image.http_image
image = cls.create_image(name=name,
@@ -148,9 +143,9 @@
@classmethod
def _create_standard_image(cls, name, container_format,
disk_format, size):
- """
- Create a new standard image and return the ID of the newly-registered
- image. Note that the size of the new image is a random number between
+ """Create a new standard image and return newly-registered image-id
+
+ Note that the size of the new image is a random number between
1024 and 4096
"""
image_file = moves.cStringIO(data_utils.random_bytes(size))
@@ -241,10 +236,8 @@
@classmethod
def _create_standard_image(cls, name, container_format,
disk_format, size):
- """
- Create a new standard image and return the ID of the newly-registered
- image.
- """
+ """Create a new standard image and return newly-registered image-id"""
+
image_file = moves.cStringIO(data_utils.random_bytes(size))
name = 'New Standard Image %s' % name
image = cls.create_image(name=name,
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index bacf211..936eadf 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -29,17 +29,15 @@
class BasicOperationsImagesTest(base.BaseV2ImageTest):
- """
- Here we test the basic operations of images
- """
+ """Here we test the basic operations of images"""
@test.attr(type='smoke')
@test.idempotent_id('139b765e-7f3d-4b3d-8b37-3ca3876ee318')
def test_register_upload_get_image_file(self):
+ """Here we test these functionalities
- """
- Here we test these functionalities - Register image,
- upload the image file, get image and get image file api's
+ Register image, upload the image file, get image and get image
+ file api's
"""
uuid = '00000000-1111-2222-3333-444455556666'
@@ -135,9 +133,7 @@
class ListImagesTest(base.BaseV2ImageTest):
- """
- Here we test the listing of image information
- """
+ """Here we test the listing of image information"""
@classmethod
def resource_setup(cls):
@@ -158,9 +154,9 @@
@classmethod
def _create_standard_image(cls, container_format, disk_format):
- """
- Create a new standard image and return the ID of the newly-registered
- image. Note that the size of the new image is a random number between
+ """Create a new standard image and return the newly-registered image-id
+
+ Note that the size of the new image is a random number between
1024 and 4096
"""
size = random.randint(1024, 4096)
@@ -176,9 +172,8 @@
return image_id
def _list_by_param_value_and_assert(self, params):
- """
- Perform list action with given params and validates result.
- """
+ """Perform list action with given params and validates result."""
+
images_list = self.client.list_images(params=params)['images']
# Validating params of fetched images
for image in images_list:
diff --git a/tempest/api/image/v2/test_images_metadefs_namespaces.py b/tempest/api/image/v2/test_images_metadefs_namespaces.py
index 21247b1..d089c84 100644
--- a/tempest/api/image/v2/test_images_metadefs_namespaces.py
+++ b/tempest/api/image/v2/test_images_metadefs_namespaces.py
@@ -20,9 +20,8 @@
class MetadataNamespacesTest(base.BaseV2ImageTest):
- """
- Here we will test the Metadata definition Namespaces basic functionality.
- """
+ """Test the Metadata definition Namespaces basic functionality"""
+
@test.idempotent_id('319b765e-7f3d-4b3d-8b37-3ca3876ee768')
def test_basic_metadata_definition_namespaces(self):
# get the available resource types and use one resource_type
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index c5c5e8b..71c8c7a 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -24,8 +24,7 @@
class ImagesNegativeTest(base.BaseV2ImageTest):
- """
- here we have -ve tests for show_image and delete_image api
+ """here we have -ve tests for show_image and delete_image api
Tests
** get non-existent image
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 64a7fd5..39dc7c3 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -26,8 +26,7 @@
class BaseMessagingTest(test.BaseTestCase):
- """
- Base class for the Messaging tests that use the Tempest Zaqar REST client
+ """Base class for the Messaging (Zaqar) tests
It is assumed that the following option is defined in the
[service_available] section of etc/tempest.conf
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 41a7d65..2621581 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -90,10 +90,8 @@
pass
def assertHeaders(self, resp, target, method):
- """
- Common method to check the existence and the format of common response
- headers
- """
+ """Check the existence and the format of response headers"""
+
self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
target, method))
self.assertThat(resp, custom_matchers.AreAllWellFormatted())
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 78707d8..0f6a330 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -92,8 +92,7 @@
@test.idempotent_id('63f51f9f-5f1d-4fc6-b5be-d454d70949d6')
@test.requires_ext(extension='account_quotas', service='object')
def test_admin_modify_quota(self):
- """Test that the ResellerAdmin is able to modify and remove the quota
- on a user's account.
+ """Test ResellerAdmin can modify/remove the quota on a user's account
Using the account client, the test modifies the quota
successively to:
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 2bf331a..aee17d3 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -83,9 +83,7 @@
@test.idempotent_id('d1dc5076-555e-4e6d-9697-28f1fe976324')
@test.requires_ext(extension='account_quotas', service='object')
def test_user_modify_quota(self):
- """Test that a user is not able to modify or remove a quota on
- its account.
- """
+ """Test that a user cannot modify or remove a quota on its account."""
# Not able to remove quota
self.assertRaises(lib_exc.Forbidden,
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index d22fb25..e2ac455 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -16,7 +16,7 @@
import netaddr
from tempest.api.orchestration import base
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -38,7 +38,7 @@
@classmethod
def setup_credentials(cls):
super(NeutronResourcesTestJSON, cls).setup_credentials()
- cls.os = clients.Manager()
+ cls.os = credentials.ConfiguredUserManager()
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index e37587c..4bc2c17 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -91,8 +91,7 @@
@test.idempotent_id('c951d55e-7cce-4c1f-83a0-bad735437fa6')
def test_list_resources(self):
- """Getting list of created resources for the stack should be possible.
- """
+ """Get list of created resources for the stack should be possible."""
resources = self.list_resources(self.stack_identifier)
self.assertEqual({self.resource_name: self.resource_type}, resources)
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 8f07614..81f00ec 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -112,8 +112,8 @@
super(BaseTelemetryTest, cls).resource_cleanup()
def await_samples(self, metric, query):
- """
- This method is to wait for sample to add it to database.
+ """This method is to wait for sample to add it to database.
+
There are long time delays when using Postgresql (or Mysql)
database as ceilometer backend
"""
diff --git a/tempest/api/telemetry/test_alarming_api_negative.py b/tempest/api/telemetry/test_alarming_api_negative.py
index 7d5a0bf..06753b0 100644
--- a/tempest/api/telemetry/test_alarming_api_negative.py
+++ b/tempest/api/telemetry/test_alarming_api_negative.py
@@ -21,8 +21,8 @@
class TelemetryAlarmingNegativeTest(base.BaseTelemetryTest):
- """here we have negative tests for show_alarm, update_alarm, show_alarm_history
- Tests
+ """Negative tests for show_alarm, update_alarm, show_alarm_history tests
+
** show non-existent alarm
** show the deleted alarm
** delete deleted alarm
diff --git a/tempest/api/volume/admin/test_volume_services.py b/tempest/api/volume/admin/test_volume_services.py
index 74fffb9..6692594 100644
--- a/tempest/api/volume/admin/test_volume_services.py
+++ b/tempest/api/volume/admin/test_volume_services.py
@@ -18,8 +18,8 @@
class VolumesServicesV2TestJSON(base.BaseVolumeAdminTest):
- """
- Tests Volume Services API.
+ """Tests Volume Services API.
+
volume service list requires admin privileges.
"""
diff --git a/tempest/api/volume/test_availability_zone.py b/tempest/api/volume/test_availability_zone.py
index 366b8d2..fe51375 100644
--- a/tempest/api/volume/test_availability_zone.py
+++ b/tempest/api/volume/test_availability_zone.py
@@ -18,10 +18,7 @@
class AvailabilityZoneV2TestJSON(base.BaseVolumeTest):
-
- """
- Tests Availability Zone V2 API List
- """
+ """Tests Availability Zone V2 API List"""
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 620366a..b776494 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -26,14 +26,11 @@
class VolumesV2ListTestJSON(base.BaseVolumeTest):
-
- """
- This test creates a number of 1G volumes. To run successfully,
- ensure that the backing file for the volume group that Nova uses
- has space for at least 3 1G volumes!
- If you are running a Devstack environment, ensure that the
- VOLUME_BACKING_FILE_SIZE is at least 4G in your localrc
- """
+ # NOTE: This test creates a number of 1G volumes. To run successfully,
+ # ensure that the backing file for the volume group that Nova uses
+ # has space for at least 3 1G volumes!
+ # If you are running a Devstack environment, ensure that the
+ # VOLUME_BACKING_FILE_SIZE is at least 4G in your localrc
VOLUME_FIELDS = ('id', 'name')
@@ -83,10 +80,7 @@
super(VolumesV2ListTestJSON, cls).resource_cleanup()
def _list_by_param_value_and_assert(self, params, with_detail=False):
- """
- Perform list or list_details action with given params
- and validates result.
- """
+ """list or list_details with given params and validates result"""
if with_detail:
fetched_vol_list = \
self.client.list_volumes(detail=True, params=params)['volumes']
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 9866da3..856adcc 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -43,10 +43,8 @@
self.volumes_client.wait_for_volume_status(volume_id, 'available')
def _list_by_param_values_and_assert(self, params, with_detail=False):
- """
- Perform list or list_details action with given params
- and validates result.
- """
+ """list or list_details with given params and validates result."""
+
if with_detail:
fetched_snap_list = self.snapshots_client.list_snapshots(
detail=True, params=params)['snapshots']
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 94a9d16..6568627 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -21,9 +21,7 @@
class VolumesV2ListTestJSON(base.BaseVolumeTest):
-
- """
- volumes v2 specific tests.
+ """volumes v2 specific tests.
This test creates a number of 1G volumes. To run successfully,
ensure that the backing file for the volume group that Nova uses
diff --git a/tempest/clients.py b/tempest/clients.py
index 6d25369..cab7512 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -38,7 +38,6 @@
from tempest_lib.services.identity.v2.token_client import TokenClient
from tempest_lib.services.identity.v3.token_client import V3TokenClient
-from tempest.common import cred_provider
from tempest.common import negative_rest_client
from tempest import config
from tempest import exceptions
@@ -175,7 +174,7 @@
}
default_params_with_timeout_values.update(default_params)
- def __init__(self, credentials=None, service=None):
+ def __init__(self, credentials, service=None):
super(Manager, self).__init__(credentials=credentials)
self._set_compute_clients()
@@ -484,17 +483,3 @@
self.account_client = AccountClient(self.auth_provider, **params)
self.container_client = ContainerClient(self.auth_provider, **params)
self.object_client = ObjectClient(self.auth_provider, **params)
-
-
-class AdminManager(Manager):
-
- """
- Manager object that uses the admin credentials for its
- managed client objects
- """
-
- def __init__(self, service=None):
- super(AdminManager, self).__init__(
- credentials=cred_provider.get_configured_credentials(
- 'identity_admin'),
- service=service)
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index 8b84bea..239b4e9 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -58,7 +58,7 @@
from tempest import clients
from tempest.cmd import cleanup_service
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as credentials
from tempest import config
SAVED_STATE_JSON = "saved_state.json"
@@ -75,7 +75,7 @@
def take_action(self, parsed_args):
cleanup_service.init_conf()
self.options = parsed_args
- self.admin_mgr = clients.AdminManager()
+ self.admin_mgr = credentials.AdminManager()
self.dry_run_data = {}
self.json_data = {}
@@ -162,7 +162,7 @@
kwargs = {"username": CONF.auth.admin_username,
"password": CONF.auth.admin_password,
"tenant_name": tenant['name']}
- mgr = clients.Manager(credentials=cred_provider.get_credentials(
+ mgr = clients.Manager(credentials=credentials.get_credentials(
**kwargs))
kwargs = {'data': tenant_data,
'is_dry_run': is_dry_run,
@@ -235,7 +235,7 @@
LOG.debug("Remove admin user role for tenant: %s" % tenant_id)
# Must initialize AdminManager for each user role
# Otherwise authentication exception is thrown, weird
- id_cl = clients.AdminManager().identity_client
+ id_cl = credentials.AdminManager().identity_client
if (self._tenant_exists(tenant_id)):
try:
id_cl.remove_user_role(tenant_id, self.admin_id,
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 40a079c..d2f6c03 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -16,7 +16,7 @@
from oslo_log import log as logging
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest import test
@@ -82,7 +82,7 @@
def _get_network_id(net_name, tenant_name):
- am = clients.AdminManager()
+ am = credentials.AdminManager()
net_cl = am.networks_client
id_cl = am.identity_client
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 2811070..9c8e2a0 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -24,7 +24,7 @@
from six.moves.urllib import parse as urlparse
from tempest import clients
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 3575998..e5f24b3 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -18,83 +18,10 @@
import six
from tempest_lib import auth
-from tempest import config
from tempest import exceptions
-CONF = config.CONF
LOG = logging.getLogger(__name__)
-# Type of credentials available from configuration
-CREDENTIAL_TYPES = {
- 'identity_admin': ('auth', 'admin'),
- 'user': ('identity', None),
- 'alt_user': ('identity', 'alt')
-}
-
-DEFAULT_PARAMS = {
- 'disable_ssl_certificate_validation':
- CONF.identity.disable_ssl_certificate_validation,
- 'ca_certs': CONF.identity.ca_certificates_file,
- 'trace_requests': CONF.debug.trace_requests
-}
-
-
-# Read credentials from configuration, builds a Credentials object
-# based on the specified or configured version
-def get_configured_credentials(credential_type, fill_in=True,
- identity_version=None):
- identity_version = identity_version or CONF.identity.auth_version
- if identity_version not in ('v2', 'v3'):
- raise exceptions.InvalidConfiguration(
- 'Unsupported auth version: %s' % identity_version)
- if credential_type not in CREDENTIAL_TYPES:
- raise exceptions.InvalidCredentials()
- conf_attributes = ['username', 'password', 'tenant_name']
- if identity_version == 'v3':
- conf_attributes.append('domain_name')
- # Read the parts of credentials from config
- params = DEFAULT_PARAMS.copy()
- section, prefix = CREDENTIAL_TYPES[credential_type]
- for attr in conf_attributes:
- _section = getattr(CONF, section)
- if prefix is None:
- params[attr] = getattr(_section, attr)
- else:
- params[attr] = getattr(_section, prefix + "_" + attr)
- # Build and validate credentials. We are reading configured credentials,
- # so validate them even if fill_in is False
- credentials = get_credentials(fill_in=fill_in,
- identity_version=identity_version, **params)
- if not fill_in:
- if not credentials.is_valid():
- msg = ("The %s credentials are incorrectly set in the config file."
- " Double check that all required values are assigned" %
- credential_type)
- raise exceptions.InvalidConfiguration(msg)
- return credentials
-
-
-# Wrapper around auth.get_credentials to use the configured identity version
-# is none is specified
-def get_credentials(fill_in=True, identity_version=None, **kwargs):
- params = dict(DEFAULT_PARAMS, **kwargs)
- identity_version = identity_version or CONF.identity.auth_version
- # In case of "v3" add the domain from config if not specified
- if identity_version == 'v3':
- domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
- if 'domain' in x)
- if not domain_fields.intersection(kwargs.keys()):
- domain_name = CONF.auth.default_credentials_domain_name
- params['user_domain_name'] = domain_name
-
- auth_url = CONF.identity.uri_v3
- else:
- auth_url = CONF.identity.uri
- return auth.get_credentials(auth_url,
- fill_in=fill_in,
- identity_version=identity_version,
- **params)
-
@six.add_metaclass(abc.ABCMeta)
class CredentialProvider(object):
diff --git a/tempest/common/credentials.py b/tempest/common/credentials.py
deleted file mode 100644
index 76f8afe..0000000
--- a/tempest/common/credentials.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-
-from tempest.common import cred_provider
-from tempest.common import dynamic_creds
-from tempest.common import preprov_creds
-from tempest import config
-from tempest import exceptions
-
-CONF = config.CONF
-
-
-# Return the right implementation of CredentialProvider based on config
-# Dropping interface and password, as they are never used anyways
-# TODO(andreaf) Drop them from the CredentialsProvider interface completely
-def get_credentials_provider(name, network_resources=None,
- force_tenant_isolation=False,
- identity_version=None):
- # If a test requires a new account to work, it can have it via forcing
- # dynamic credentials. A new account will be produced only for that test.
- # In case admin credentials are not available for the account creation,
- # the test should be skipped else it would fail.
- identity_version = identity_version or CONF.identity.auth_version
- if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
- return dynamic_creds.DynamicCredentialProvider(
- name=name,
- network_resources=network_resources,
- identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role)
- else:
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- # Most params are not relevant for pre-created accounts
- return preprov_creds.PreProvisionedCredentialProvider(
- name=name, identity_version=identity_version,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role)
- else:
- return preprov_creds.NonLockingCredentialProvider(
- name=name, identity_version=identity_version,
- admin_role=CONF.identity.admin_role)
-
-
-# We want a helper function here to check and see if admin credentials
-# are available so we can do a single call from skip_checks if admin
-# creds area available.
-# This depends on identity_version as there may be admin credentials
-# available for v2 but not for v3.
-def is_admin_available(identity_version):
- is_admin = True
- # If dynamic credentials is enabled admin will be available
- if CONF.auth.use_dynamic_credentials:
- return is_admin
- # Check whether test accounts file has the admin specified or not
- elif (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_admin',
- admin_role=CONF.identity.admin_role)
- if not check_accounts.admin_available():
- is_admin = False
- else:
- try:
- cred_provider.get_configured_credentials(
- 'identity_admin', fill_in=False,
- identity_version=identity_version)
- except exceptions.InvalidConfiguration:
- is_admin = False
- return is_admin
-
-
-# We want a helper function here to check and see if alt credentials
-# are available so we can do a single call from skip_checks if alt
-# creds area available.
-# This depends on identity_version as there may be alt credentials
-# available for v2 but not for v3.
-def is_alt_available(identity_version):
- # If dynamic credentials is enabled alt will be available
- if CONF.auth.use_dynamic_credentials:
- return True
- # Check whether test accounts file has the admin specified or not
- if (CONF.auth.test_accounts_file and
- os.path.isfile(CONF.auth.test_accounts_file)):
- check_accounts = preprov_creds.PreProvisionedCredentialProvider(
- identity_version=identity_version, name='check_alt',
- admin_role=CONF.identity.admin_role)
- else:
- check_accounts = preprov_creds.NonLockingCredentialProvider(
- identity_version=identity_version, name='check_alt',
- admin_role=CONF.identity.admin_role)
- try:
- if not check_accounts.is_multi_user():
- return False
- else:
- return True
- except exceptions.InvalidConfiguration:
- return False
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
new file mode 100644
index 0000000..486b7fd
--- /dev/null
+++ b/tempest/common/credentials_factory.py
@@ -0,0 +1,316 @@
+# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+
+from oslo_log import log as logging
+from tempest_lib import auth
+
+from tempest import clients
+from tempest.common import cred_provider
+from tempest.common import dynamic_creds
+from tempest.common import preprov_creds
+from tempest import config
+from tempest import exceptions
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+"""This module provides factories of credential and credential providers
+
+Credentials providers and clients are (going to be) part of tempest-lib,
+and so they may not hold any dependency to tempest configuration.
+
+Methods in this module collect the relevant configuration details and pass
+them to credentials providers and clients, so that test can have easy
+access to these features.
+
+Client managers with hard-coded configured credentials are also moved here,
+to avoid circular dependencies."""
+
+# === Credential Providers
+
+
+class LegacyCredentialProvider(cred_provider.CredentialProvider):
+
+ def __init__(self, identity_version):
+ """Credentials provider which returns credentials from tempest.conf
+
+ Credentials provider which always returns the first and second
+ configured accounts as primary and alt users.
+ Credentials from tempest.conf are deprecated, and this credential
+ provider is also accordingly.
+
+ This credential provider can be used in case of serial test execution
+ to preserve the current behaviour of the serial tempest run.
+
+ :param identity_version: Version of the identity API
+ :return: CredentialProvider
+ """
+ super(LegacyCredentialProvider, self).__init__(
+ identity_version=identity_version)
+ self._creds = {}
+
+ def _unique_creds(self, cred_arg=None):
+ """Verify that the configured credentials are valid and distinct """
+ try:
+ user = self.get_primary_creds()
+ alt_user = self.get_alt_creds()
+ return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
+ except exceptions.InvalidCredentials as ic:
+ msg = "At least one of the configured credentials is " \
+ "not valid: %s" % ic.message
+ raise exceptions.InvalidConfiguration(msg)
+
+ def is_multi_user(self):
+ return self._unique_creds('username')
+
+ def is_multi_tenant(self):
+ return self._unique_creds('tenant_id')
+
+ def get_primary_creds(self):
+ if self._creds.get('primary'):
+ return self._creds.get('primary')
+ primary_credential = get_configured_credentials(
+ credential_type='user', fill_in=False,
+ identity_version=self.identity_version)
+ self._creds['primary'] = cred_provider.TestResources(
+ primary_credential)
+ return self._creds['primary']
+
+ def get_alt_creds(self):
+ if self._creds.get('alt'):
+ return self._creds.get('alt')
+ alt_credential = get_configured_credentials(
+ credential_type='alt_user', fill_in=False,
+ identity_version=self.identity_version)
+ self._creds['alt'] = cred_provider.TestResources(
+ alt_credential)
+ return self._creds['alt']
+
+ def clear_creds(self):
+ self._creds = {}
+
+ def get_admin_creds(self):
+ if self._creds.get('admin'):
+ return self._creds.get('admin')
+ creds = get_configured_credentials(
+ "identity_admin", fill_in=False)
+ self._creds['admin'] = cred_provider.TestResources(creds)
+ return self._creds['admin']
+
+ def get_creds_by_roles(self, roles, force_new=False):
+ msg = "Credentials being specified through the config file can not be"\
+ " used with tests that specify using credentials by roles. "\
+ "Either exclude/skip the tests doing this or use either an "\
+ "test_accounts_file or dynamic credentials."
+ raise exceptions.InvalidConfiguration(msg)
+
+ def is_role_available(self, role):
+ msg = "Credentials being specified through the config file can not be"\
+ " used with tests that specify using credentials by roles. "\
+ "Either exclude/skip the tests doing this or use either an "\
+ "test_accounts_file or dynamic credentials."
+ raise exceptions.InvalidConfiguration(msg)
+
+
+# Return the right implementation of CredentialProvider based on config
+# Dropping interface and password, as they are never used anyways
+# TODO(andreaf) Drop them from the CredentialsProvider interface completely
+def get_credentials_provider(name, network_resources=None,
+ force_tenant_isolation=False,
+ identity_version=None):
+ # If a test requires a new account to work, it can have it via forcing
+ # dynamic credentials. A new account will be produced only for that test.
+ # In case admin credentials are not available for the account creation,
+ # the test should be skipped else it would fail.
+ identity_version = identity_version or CONF.identity.auth_version
+ if CONF.auth.use_dynamic_credentials or force_tenant_isolation:
+ admin_creds = get_configured_credentials(
+ 'identity_admin', fill_in=True, identity_version=identity_version)
+ return dynamic_creds.DynamicCredentialProvider(
+ name=name,
+ network_resources=network_resources,
+ identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role,
+ admin_creds=admin_creds)
+ else:
+ if (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ # Most params are not relevant for pre-created accounts
+ return preprov_creds.PreProvisionedCredentialProvider(
+ name=name, identity_version=identity_version,
+ credentials_domain=CONF.auth.default_credentials_domain_name,
+ admin_role=CONF.identity.admin_role)
+ else:
+ # Dynamic credentials are disabled, and the account file is not
+ # defined - we fall back on credentials configured in tempest.conf
+ return LegacyCredentialProvider(identity_version=identity_version)
+
+
+# We want a helper function here to check and see if admin credentials
+# are available so we can do a single call from skip_checks if admin
+# creds area available.
+# This depends on identity_version as there may be admin credentials
+# available for v2 but not for v3.
+def is_admin_available(identity_version):
+ is_admin = True
+ # If dynamic credentials is enabled admin will be available
+ if CONF.auth.use_dynamic_credentials:
+ return is_admin
+ # Check whether test accounts file has the admin specified or not
+ elif (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_admin',
+ admin_role=CONF.identity.admin_role)
+ if not check_accounts.admin_available():
+ is_admin = False
+ else:
+ try:
+ get_configured_credentials('identity_admin', fill_in=False,
+ identity_version=identity_version)
+ except exceptions.InvalidConfiguration:
+ is_admin = False
+ return is_admin
+
+
+# We want a helper function here to check and see if alt credentials
+# are available so we can do a single call from skip_checks if alt
+# creds area available.
+# This depends on identity_version as there may be alt credentials
+# available for v2 but not for v3.
+def is_alt_available(identity_version):
+ # If dynamic credentials is enabled alt will be available
+ if CONF.auth.use_dynamic_credentials:
+ return True
+ # Check whether test accounts file has the admin specified or not
+ if (CONF.auth.test_accounts_file and
+ os.path.isfile(CONF.auth.test_accounts_file)):
+ check_accounts = preprov_creds.PreProvisionedCredentialProvider(
+ identity_version=identity_version, name='check_alt',
+ admin_role=CONF.identity.admin_role)
+ else:
+ check_accounts = LegacyCredentialProvider(identity_version)
+ try:
+ if not check_accounts.is_multi_user():
+ return False
+ else:
+ return True
+ except exceptions.InvalidConfiguration:
+ return False
+
+# === Credentials
+
+# Type of credentials available from configuration
+CREDENTIAL_TYPES = {
+ 'identity_admin': ('auth', 'admin'),
+ 'user': ('identity', None),
+ 'alt_user': ('identity', 'alt')
+}
+
+DEFAULT_PARAMS = {
+ 'disable_ssl_certificate_validation':
+ CONF.identity.disable_ssl_certificate_validation,
+ 'ca_certs': CONF.identity.ca_certificates_file,
+ 'trace_requests': CONF.debug.trace_requests
+}
+
+
+# Read credentials from configuration, builds a Credentials object
+# based on the specified or configured version
+def get_configured_credentials(credential_type, fill_in=True,
+ identity_version=None):
+ identity_version = identity_version or CONF.identity.auth_version
+
+ if identity_version not in ('v2', 'v3'):
+ raise exceptions.InvalidConfiguration(
+ 'Unsupported auth version: %s' % identity_version)
+
+ if credential_type not in CREDENTIAL_TYPES:
+ raise exceptions.InvalidCredentials()
+ conf_attributes = ['username', 'password', 'tenant_name']
+
+ if identity_version == 'v3':
+ conf_attributes.append('domain_name')
+ # Read the parts of credentials from config
+ params = DEFAULT_PARAMS.copy()
+ section, prefix = CREDENTIAL_TYPES[credential_type]
+ for attr in conf_attributes:
+ _section = getattr(CONF, section)
+ if prefix is None:
+ params[attr] = getattr(_section, attr)
+ else:
+ params[attr] = getattr(_section, prefix + "_" + attr)
+ # Build and validate credentials. We are reading configured credentials,
+ # so validate them even if fill_in is False
+ credentials = get_credentials(fill_in=fill_in,
+ identity_version=identity_version, **params)
+ if not fill_in:
+ if not credentials.is_valid():
+ msg = ("The %s credentials are incorrectly set in the config file."
+ " Double check that all required values are assigned" %
+ credential_type)
+ raise exceptions.InvalidConfiguration(msg)
+ return credentials
+
+
+# Wrapper around auth.get_credentials to use the configured identity version
+# is none is specified
+def get_credentials(fill_in=True, identity_version=None, **kwargs):
+ params = dict(DEFAULT_PARAMS, **kwargs)
+ identity_version = identity_version or CONF.identity.auth_version
+ # In case of "v3" add the domain from config if not specified
+ if identity_version == 'v3':
+ domain_fields = set(x for x in auth.KeystoneV3Credentials.ATTRIBUTES
+ if 'domain' in x)
+ if not domain_fields.intersection(kwargs.keys()):
+ domain_name = CONF.auth.default_credentials_domain_name
+ params['user_domain_name'] = domain_name
+
+ auth_url = CONF.identity.uri_v3
+ else:
+ auth_url = CONF.identity.uri
+ return auth.get_credentials(auth_url,
+ fill_in=fill_in,
+ identity_version=identity_version,
+ **params)
+
+# === Credential / client managers
+
+
+class ConfiguredUserManager(clients.Manager):
+ """
+ Manager object that uses the `user` credentials for its
+ managed client objects
+ """
+
+ def __init__(self, service=None):
+ super(ConfiguredUserManager, self).__init__(
+ credentials=get_configured_credentials('user'),
+ service=service)
+
+
+class AdminManager(clients.Manager):
+
+ """
+ Manager object that uses the admin credentials for its
+ managed client objects
+ """
+
+ def __init__(self, service=None):
+ super(AdminManager, self).__init__(
+ credentials=get_configured_credentials('identity_admin'),
+ service=service)
diff --git a/tempest/common/dynamic_creds.py b/tempest/common/dynamic_creds.py
index ce69c84..ae53543 100644
--- a/tempest/common/dynamic_creds.py
+++ b/tempest/common/dynamic_creds.py
@@ -31,16 +31,32 @@
class DynamicCredentialProvider(cred_provider.CredentialProvider):
def __init__(self, identity_version, name=None, network_resources=None,
- credentials_domain=None, admin_role=None):
+ credentials_domain=None, admin_role=None, admin_creds=None):
+ """Creates credentials dynamically for tests
+
+ A credential provider that, based on an initial set of
+ admin credentials, creates new credentials on the fly for
+ tests to use and then discard.
+
+ :param str identity_version: identity API version to use `v2` or `v3`
+ :param str admin_role: name of the admin role added to admin users
+ :param str name: names of dynamic resources include this parameter
+ when specified
+ :param str credentials_domain: name of the domain where the users
+ are created. If not defined, the project
+ domain from admin_credentials is used
+ :param dict network_resources: network resources to be created for
+ the created credentials
+ :param Credentials admin_creds: initial admin credentials
+ """
super(DynamicCredentialProvider, self).__init__(
- identity_version=identity_version, name=name,
- network_resources=network_resources,
- credentials_domain=credentials_domain, admin_role=admin_role)
+ identity_version=identity_version, admin_role=admin_role,
+ name=name, credentials_domain=credentials_domain,
+ network_resources=network_resources)
+ self.network_resources = network_resources
self._creds = {}
self.ports = []
- self.default_admin_creds = cred_provider.get_configured_credentials(
- 'identity_admin', fill_in=True,
- identity_version=self.identity_version)
+ self.default_admin_creds = admin_creds
(self.identity_admin_client, self.network_admin_client,
self.networks_admin_client,
self.subnets_admin_client,
diff --git a/tempest/common/preprov_creds.py b/tempest/common/preprov_creds.py
index dd27f08..f711302 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/common/preprov_creds.py
@@ -310,64 +310,3 @@
if not user_domain_fields.intersection(set(creds_dict.keys())):
creds_dict['user_domain_name'] = self.credentials_domain
return creds_dict
-
-
-class NonLockingCredentialProvider(PreProvisionedCredentialProvider):
- """Credentials provider which always returns the first and second
- configured accounts as primary and alt users.
- This credential provider can be used in case of serial test execution
- to preserve the current behaviour of the serial tempest run.
- """
-
- def _unique_creds(self, cred_arg=None):
- """Verify that the configured credentials are valid and distinct """
- try:
- user = self.get_primary_creds()
- alt_user = self.get_alt_creds()
- return getattr(user, cred_arg) != getattr(alt_user, cred_arg)
- except exceptions.InvalidCredentials as ic:
- msg = "At least one of the configured credentials is " \
- "not valid: %s" % ic.message
- raise exceptions.InvalidConfiguration(msg)
-
- def is_multi_user(self):
- return self._unique_creds('username')
-
- def is_multi_tenant(self):
- return self._unique_creds('tenant_id')
-
- def get_primary_creds(self):
- if self._creds.get('primary'):
- return self._creds.get('primary')
- primary_credential = cred_provider.get_configured_credentials(
- fill_in=False, credential_type='user',
- identity_version=self.identity_version)
- self._creds['primary'] = cred_provider.TestResources(
- primary_credential)
- return self._creds['primary']
-
- def get_alt_creds(self):
- if self._creds.get('alt'):
- return self._creds.get('alt')
- alt_credential = cred_provider.get_configured_credentials(
- fill_in=False, credential_type='alt_user',
- identity_version=self.identity_version)
- self._creds['alt'] = cred_provider.TestResources(
- alt_credential)
- return self._creds['alt']
-
- def clear_creds(self):
- self._creds = {}
-
- def get_admin_creds(self):
- creds = cred_provider.get_configured_credentials(
- "identity_admin", fill_in=False)
- self._creds['admin'] = cred_provider.TestResources(creds)
- return self._creds['admin']
-
- def get_creds_by_roles(self, roles, force_new=False):
- msg = "Credentials being specified through the config file can not be"\
- " used with tests that specify using credentials by roles. "\
- "Either exclude/skip the tests doing this or use either an "\
- "test_accounts_file or dynamic credentials."
- raise exceptions.InvalidConfiguration(msg)
diff --git a/tempest/hacking/ignored_list_T110.txt b/tempest/hacking/ignored_list_T110.txt
index 987861f..7c3e830 100644
--- a/tempest/hacking/ignored_list_T110.txt
+++ b/tempest/hacking/ignored_list_T110.txt
@@ -1,4 +1,3 @@
-./tempest/services/compute/json/server_groups_client.py
./tempest/services/compute/json/servers_client.py
./tempest/services/database/json/flavors_client.py
./tempest/services/identity/v3/json/credentials_client.py
diff --git a/tempest/manager.py b/tempest/manager.py
index d7c3128..b0541e8 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -31,22 +31,18 @@
and a client object for a test case to use in performing actions.
"""
- def __init__(self, credentials=None):
+ def __init__(self, credentials):
"""
- We allow overriding of the credentials used within the various
- client classes managed by the Manager object. Left as None, the
- standard username/password/tenant_name[/domain_name] is used.
+ Credentials to be used within the various client classes managed by the
+ Manager object must be defined.
- :param credentials: Override of the credentials
+ :param credentials: type Credentials or TestResources
"""
- self.auth_version = CONF.identity.auth_version
- if credentials is None:
- self.credentials = cred_provider.get_configured_credentials('user')
- else:
- self.credentials = credentials
+ self.credentials = credentials
# Check if passed or default credentials are valid
if not self.credentials.is_valid():
raise exceptions.InvalidCredentials()
+ self.auth_version = CONF.identity.auth_version
# Tenant isolation creates TestResources, but
# PreProvisionedCredentialProvider and some tests create Credentials
if isinstance(credentials, cred_provider.TestResources):
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index ffeda1b..9f283c5 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -131,14 +131,13 @@
self.cleanup_waits.append(wait_dict)
def _wait_for_cleanups(self):
- """To handle async delete actions, a list of waits is added
- which will be iterated over as the last step of clearing the
- cleanup queue. That way all the delete calls are made up front
- and the tests won't succeed unless the deletes are eventually
- successful. This is the same basic approach used in the api tests to
- limit cleanup execution time except here it is multi-resource,
- because of the nature of the scenario tests.
- """
+ # To handle async delete actions, a list of waits is added
+ # which will be iterated over as the last step of clearing the
+ # cleanup queue. That way all the delete calls are made up front
+ # and the tests won't succeed unless the deletes are eventually
+ # successful. This is the same basic approach used in the api tests to
+ # limit cleanup execution time except here it is multi-resource,
+ # because of the nature of the scenario tests.
for wait in self.cleanup_waits:
waiter_callable = wait.pop('waiter_callable')
waiter_callable(**wait)
@@ -519,7 +518,8 @@
username=None,
private_key=None,
should_connect=True):
- """
+ """Check server connectivity
+
:param ip_address: server to test against
:param username: server's ssh username
:param private_key: server's ssh private key to be used
@@ -562,9 +562,7 @@
raise
def create_floating_ip(self, thing, pool_name=None):
- """Creates a floating IP and associates to a server using
- Nova clients
- """
+ """Create a floating IP and associates to a server on Nova"""
floating_ip = (self.compute_floating_ips_client.
create_floating_ip(pool_name)['floating_ip'])
@@ -602,9 +600,17 @@
ssh_client.umount(mount_path)
return timestamp
+ def get_server_or_ip(self, server):
+ if CONF.validation.connect_method == 'floating':
+ ip = self.create_floating_ip(server)['ip']
+ else:
+ ip = server
+ return ip
+
class NetworkScenarioTest(ScenarioTest):
"""Base class for network scenario tests.
+
This class provide helpers for network scenario tests, using the neutron
API. Helpers from ancestor which use the nova network API are overridden
with the neutron API.
@@ -675,9 +681,9 @@
def _create_subnet(self, network, client=None, subnets_client=None,
namestart='subnet-smoke', **kwargs):
- """
- Create a subnet for the given network within the cidr block
- configured for tenant networks.
+ """Create a subnet for the given network
+
+ within the cidr block configured for tenant networks.
"""
if not client:
client = self.network_client
@@ -685,7 +691,8 @@
subnets_client = self.subnets_client
def cidr_in_use(cidr, tenant_id):
- """
+ """Check cidr existence
+
:return True if subnet with cidr already exist in tenant
False else
"""
@@ -775,9 +782,7 @@
def create_floating_ip(self, thing, external_network_id=None,
port_id=None, client=None):
- """Creates a floating IP and associates to a resource/port using
- Neutron client
- """
+ """Create a floating IP and associates to a resource/port on Neutron"""
if not external_network_id:
external_network_id = CONF.network.public_network_id
if not client:
@@ -805,9 +810,7 @@
return floating_ip
def _disassociate_floating_ip(self, floating_ip):
- """
- :param floating_ip: type DeletableFloatingIp
- """
+ """:param floating_ip: type DeletableFloatingIp"""
floating_ip.update(port_id=None)
self.assertIsNone(floating_ip.port_id)
return floating_ip
@@ -860,8 +863,7 @@
raise
def _check_remote_connectivity(self, source, dest, should_succeed=True):
- """
- check ping server via source ssh connection
+ """check ping server via source ssh connection
:param source: RemoteClient: an ssh connection from which to ping
:param dest: and IP to ping against
@@ -992,7 +994,9 @@
return sg_rule
def _create_loginable_secgroup_rule(self, client=None, secgroup=None):
- """These rules are intended to permit inbound ssh and icmp
+ """Create loginable security group rule
+
+ These rules are intended to permit inbound ssh and icmp
traffic from all sources, so no group_id is provided.
Setting a group_id would only permit traffic from ports
belonging to the same security group.
@@ -1353,9 +1357,7 @@
class EncryptionScenarioTest(ScenarioTest):
- """
- Base class for encryption scenario tests
- """
+ """Base class for encryption scenario tests"""
credentials = ['primary', 'admin']
@@ -1405,8 +1407,7 @@
class ObjectStorageScenarioTest(ScenarioTest):
- """
- Provide harness to do Object Storage scenario tests.
+ """Provide harness to do Object Storage scenario tests.
Subclasses implement the tests that use the methods provided by this
class.
@@ -1474,10 +1475,8 @@
def list_and_check_container_objects(self, container_name,
present_obj=None,
not_present_obj=None):
- """
- List objects for a given container and assert which are present and
- which are not.
- """
+ # List objects for a given container and assert which are present and
+ # which are not.
if present_obj is None:
present_obj = []
if not_present_obj is None:
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 22d2603..62c0262 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -25,8 +25,8 @@
class TestAggregatesBasicOps(manager.ScenarioTest):
- """
- Creates an aggregate within an availability zone
+ """Creates an aggregate within an availability zone
+
Adds a host to the aggregate
Checks aggregate details
Updates aggregate's name
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index ed691ac..fa05577 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -26,9 +26,9 @@
class BaremetalBasicOps(manager.BaremetalScenarioTest):
- """
- This smoke test tests the pxe_ssh Ironic driver. It follows this basic
- set of operations:
+ """This smoke test tests the pxe_ssh Ironic driver.
+
+ It follows this basic set of operations:
* Creates a keypair
* Boots an instance using the keypair
* Monitors the associated Ironic node for power and
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index f6d9f88..cb6b968 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -58,7 +58,8 @@
class TestDashboardBasicOps(manager.ScenarioTest):
- """
+ """The test suite for dashboard basic operations
+
This is a basic scenario test:
* checks that the login page is available
* logs in as a regular user
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 3f0123d..99837eb 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -22,7 +22,8 @@
class TestEncryptedCinderVolumes(manager.EncryptionScenarioTest):
- """
+ """The test suite for encrypted cinder volumes
+
This test is for verifying the functionality of encrypted cinder volumes.
For both LUKS and cryptsetup encryption types, this test performs
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 63dd4f0..6497f7a 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -31,8 +31,7 @@
class TestLargeOpsScenario(manager.ScenarioTest):
- """
- Test large operations.
+ """Test large operations.
This test below:
* Spin up multiple instances in one nova call, and repeat three times
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 22aa06c..c3f3c78 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -29,8 +29,7 @@
class TestMinimumBasicScenario(manager.ScenarioTest):
- """
- This is a basic minimum scenario test.
+ """This is a basic minimum scenario test.
This test below:
* across the multiple components
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index f82e7e4..151eef8 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -70,12 +70,13 @@
'security_groups': [{'name': self.sec_grp['name']}]}
def prepare_network(self, address6_mode, n_subnets6=1, dualnet=False):
- """Creates network with
- given number of IPv6 subnets in the given mode and
- one IPv4 subnet
- Creates router with ports on all subnets
- if dualnet - create IPv6 subnets on a different network
- :return: list of created networks
+ """Prepare network
+
+ Creates network with given number of IPv6 subnets in the given mode and
+ one IPv4 subnet.
+ Creates router with ports on all subnets.
+ if dualnet - create IPv6 subnets on a different network
+ :return: list of created networks
"""
self.network = self._create_network(tenant_id=self.tenant_id)
if dualnet:
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 49768c5..98dd705 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -25,8 +25,8 @@
class TestObjectStorageBasicOps(manager.ObjectStorageScenarioTest):
- """
- Test swift basic ops.
+ """Test swift basic ops.
+
* get swift stat.
* create container.
* upload a file to the created container.
@@ -57,6 +57,7 @@
@test.services('object_storage')
def test_swift_acl_anonymous_download(self):
"""This test will cover below steps:
+
1. Create container
2. Upload object to the new container
3. Change the ACL of the container
diff --git a/tempest/scenario/test_object_storage_telemetry_middleware.py b/tempest/scenario/test_object_storage_telemetry_middleware.py
index 3376a7c..eee4d3d 100644
--- a/tempest/scenario/test_object_storage_telemetry_middleware.py
+++ b/tempest/scenario/test_object_storage_telemetry_middleware.py
@@ -35,8 +35,8 @@
class TestObjectStorageTelemetry(manager.ObjectStorageScenarioTest):
- """
- Test that swift uses the ceilometer middleware.
+ """Test that swift uses the ceilometer middleware.
+
* create container.
* upload a file to the created container.
* retrieve the file from the created container.
@@ -57,19 +57,15 @@
cls.telemetry_client = cls.os_operator.telemetry_client
def _confirm_notifications(self, container_name, obj_name):
- """
- Loop seeking for appropriate notifications about the containers
- and objects sent to swift.
- """
+ # NOTE: Loop seeking for appropriate notifications about the containers
+ # and objects sent to swift.
def _check_samples():
- """
- Return True only if we have notifications about some
- containers and some objects and the notifications are about
- the expected containers and objects.
- Otherwise returning False will case _check_samples to be
- called again.
- """
+ # NOTE: Return True only if we have notifications about some
+ # containers and some objects and the notifications are about
+ # the expected containers and objects.
+ # Otherwise returning False will case _check_samples to be
+ # called again.
results = self.telemetry_client.list_samples(
'storage.objects.incoming.bytes')
LOG.debug('got samples %s', results)
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index d2a7ec6..29e393f 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -28,7 +28,8 @@
class TestSecurityGroupsBasicOps(manager.NetworkScenarioTest):
- """
+ """The test suite for security groups
+
This test suite assumes that Nova has been configured to
boot VM's with Neutron-managed networking, and attempts to
verify cross tenant connectivity as follows
@@ -95,8 +96,7 @@
credentials = ['primary', 'alt', 'admin']
class TenantProperties(object):
- """
- helper class to save tenant details
+ """helper class to save tenant details
id
credentials
network
@@ -232,9 +232,7 @@
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
- """
+ """creates a server and assigns to security group"""
self._set_compute_context(tenant)
if security_groups is None:
security_groups = [tenant.security_groups['default']]
@@ -268,11 +266,9 @@
tenant.servers.append(server)
def _set_access_point(self, tenant):
- """
- creates a server in a secgroup with rule allowing external ssh
- in order to access tenant internal network
- workaround ip namespace
- """
+ # creates a server in a secgroup with rule allowing external ssh
+ # in order to access tenant internal network
+ # workaround ip namespace
secgroups = tenant.security_groups.values()
name = 'server-{tenant}-access_point'.format(
tenant=tenant.creds.tenant_name)
@@ -301,8 +297,7 @@
return self.servers_client
def _deploy_tenant(self, tenant_or_id):
- """
- creates:
+ """creates:
network
subnet
router (if public not defined)
@@ -320,9 +315,7 @@
self._set_access_point(tenant)
def _get_server_ip(self, server, floating=False):
- """
- returns the ip (floating/internal) of a server
- """
+ """returns the ip (floating/internal) of a server"""
if floating:
server_ip = self.floating_ips[server['id']].floating_ip_address
else:
@@ -333,9 +326,7 @@
return server_ip
def _connect_to_access_point(self, tenant):
- """
- create ssh connection to tenant access point
- """
+ """create ssh connection to tenant access point"""
access_point_ssh = \
self.floating_ips[tenant.access_point['id']].floating_ip_address
private_key = tenant.keypair['private_key']
@@ -374,10 +365,8 @@
ip=self._get_server_ip(server))
def _test_cross_tenant_block(self, source_tenant, dest_tenant):
- """
- if public router isn't defined, then dest_tenant access is via
- floating-ip
- """
+ # if public router isn't defined, then dest_tenant access is via
+ # floating-ip
access_point_ssh = self._connect_to_access_point(source_tenant)
ip = self._get_server_ip(dest_tenant.access_point,
floating=self.floating_ip_access)
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index c83dbb1..9387dc7 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -28,9 +28,9 @@
class TestServerAdvancedOps(manager.ScenarioTest):
- """
- This test case stresses some advanced server instance operations:
+ """The test suite for server advanced operations
+ This test case stresses some advanced server instance operations:
* Resizing an instance
* Sequence suspend resume
"""
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index c55cff6..8a19254 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -32,9 +32,9 @@
class TestServerBasicOps(manager.ScenarioTest):
- """
- This smoke test case follows this basic set of operations:
+ """The test suite for server basic operations
+ This smoke test case follows this basic set of operations:
* Create a keypair for use in launching an instance
* Create a security group to control network access in instance
* Add simple permissive rules to the security group
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index ef78b4a..403804d 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -27,11 +27,7 @@
class TestServerMultinode(manager.ScenarioTest):
-
- """
- This is a set of tests specific to multinode testing.
-
- """
+ """This is a set of tests specific to multinode testing."""
credentials = ['primary', 'admin']
@classmethod
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 3b38888..5778107 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -27,8 +27,8 @@
class TestShelveInstance(manager.ScenarioTest):
- """
- This test shelves then unshelves a Nova instance
+ """This test shelves then unshelves a Nova instance
+
The following is the scenario outline:
* boot an instance and create a timestamp file in it
* shelve the instance
@@ -78,24 +78,17 @@
server = self.create_server(image=CONF.compute.image_ref,
create_kwargs=create_kwargs)
- if CONF.compute.use_floatingip_for_ssh:
- floating_ip = self.create_floating_ip(server)['ip']
- timestamp = self.create_timestamp(
- floating_ip, private_key=keypair['private_key'])
- else:
- timestamp = self.create_timestamp(
- server, private_key=keypair['private_key'])
+ instance_ip = self.get_server_or_ip(server)
+ timestamp = self.create_timestamp(instance_ip,
+ private_key=keypair['private_key'])
# Prevent bug #1257594 from coming back
# Unshelve used to boot the instance with the original image, not
# with the instance snapshot
self._shelve_then_unshelve_server(server)
- if CONF.compute.use_floatingip_for_ssh:
- timestamp2 = self.get_timestamp(floating_ip,
- private_key=keypair['private_key'])
- else:
- timestamp2 = self.get_timestamp(server,
- private_key=keypair['private_key'])
+
+ timestamp2 = self.get_timestamp(instance_ip,
+ private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp2)
@test.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 5ac3a7e..cd59334 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -26,8 +26,8 @@
class TestSnapshotPattern(manager.ScenarioTest):
- """
- This test is for snapshotting an instance and booting with it.
+ """This test is for snapshotting an instance and booting with it.
+
The following is the scenario outline:
* boot an instance and create a timestamp file in it
* snapshot the instance
@@ -56,13 +56,9 @@
# boot an instance and create a timestamp file in it
server = self._boot_image(CONF.compute.image_ref, keypair,
security_group)
- if CONF.compute.use_floatingip_for_ssh:
- fip_for_server = self.create_floating_ip(server)
- timestamp = self.create_timestamp(
- fip_for_server['ip'], private_key=keypair['private_key'])
- else:
- timestamp = self.create_timestamp(
- server, private_key=keypair['private_key'])
+ instance_ip = self.get_server_or_ip(server)
+ timestamp = self.create_timestamp(instance_ip,
+ private_key=keypair['private_key'])
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
@@ -72,11 +68,7 @@
keypair, security_group)
# check the existence of the timestamp file in the second instance
- if CONF.compute.use_floatingip_for_ssh:
- fip_for_snapshot = self.create_floating_ip(server_from_snapshot)
- timestamp2 = self.get_timestamp(fip_for_snapshot['ip'],
- private_key=keypair['private_key'])
- else:
- timestamp2 = self.get_timestamp(server_from_snapshot,
- private_key=keypair['private_key'])
+ server_from_snapshot_ip = self.get_server_or_ip(server_from_snapshot)
+ timestamp2 = self.get_timestamp(server_from_snapshot_ip,
+ private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 6eceeb2..05ae33e 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -33,7 +33,8 @@
class TestStampPattern(manager.ScenarioTest):
- """
+ """The test suite for both snapshoting and attaching of volume
+
This test is for snapshotting an instance/volume and attaching the volume
created from snapshot to the instance booted from snapshot.
The following is the scenario outline:
@@ -138,11 +139,7 @@
security_group)
# create and add floating IP to server1
- if CONF.compute.use_floatingip_for_ssh:
- floating_ip_for_server = self.create_floating_ip(server)
- ip_for_server = floating_ip_for_server['ip']
- else:
- ip_for_server = server
+ ip_for_server = self.get_server_or_ip(server)
self._attach_volume(server, volume)
self._wait_for_volume_available_on_the_system(ip_for_server,
@@ -167,12 +164,7 @@
keypair, security_group)
# create and add floating IP to server_from_snapshot
- if CONF.compute.use_floatingip_for_ssh:
- floating_ip_for_snapshot = self.create_floating_ip(
- server_from_snapshot)
- ip_for_snapshot = floating_ip_for_snapshot['ip']
- else:
- ip_for_snapshot = server_from_snapshot
+ ip_for_snapshot = self.get_server_or_ip(server_from_snapshot)
# attach volume2 to instance2
self._attach_volume(server_from_snapshot, volume_from_snapshot)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 414305d..96e79e6 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -25,8 +25,7 @@
class TestVolumeBootPattern(manager.ScenarioTest):
- """
- This test case attempts to reproduce the following steps:
+ """This test case attempts to reproduce the following steps:
* Create in Cinder some bootable volume importing a Glance image
* Boot an instance from the bootable volume
@@ -95,13 +94,6 @@
vol_name = data_utils.rand_name('volume')
return self.create_volume(name=vol_name, snapshot_id=snap_id)
- def _get_server_ip(self, server):
- if CONF.compute.use_floatingip_for_ssh:
- ip = self.create_floating_ip(server)['ip']
- else:
- ip = server
- return ip
-
def _delete_server(self, server):
self.servers_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client, server['id'])
@@ -119,7 +111,7 @@
keypair, security_group)
# write content to volume on instance
- ip_instance_1st = self._get_server_ip(instance_1st)
+ ip_instance_1st = self.get_server_or_ip(instance_1st)
timestamp = self.create_timestamp(ip_instance_1st,
private_key=keypair['private_key'])
@@ -131,7 +123,7 @@
keypair, security_group)
# check the content of written file
- ip_instance_2nd = self._get_server_ip(instance_2nd)
+ ip_instance_2nd = self.get_server_or_ip(instance_2nd)
timestamp2 = self.get_timestamp(ip_instance_2nd,
private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp2)
@@ -141,13 +133,13 @@
# create a 3rd instance from snapshot
volume = self._create_volume_from_snapshot(snapshot['id'])
- instance_from_snapshot = (
+ server_from_snapshot = (
self._boot_instance_from_volume(volume['id'],
keypair, security_group))
# check the content of written file
- ip_instance_from_snapshot = self._get_server_ip(instance_from_snapshot)
- timestamp3 = self.get_timestamp(ip_instance_from_snapshot,
+ server_from_snapshot_ip = self.get_server_or_ip(server_from_snapshot)
+ timestamp3 = self.get_timestamp(server_from_snapshot_ip,
private_key=keypair['private_key'])
self.assertEqual(timestamp, timestamp3)
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 12509f7..fa7c0c9 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -24,7 +24,7 @@
import testtools
from tempest import clients
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
CONF = config.CONF
@@ -72,8 +72,7 @@
@misc.singleton
class InputScenarioUtils(object):
- """
- Example usage:
+ """Example usage:
import testscenarios
(...)
@@ -124,9 +123,7 @@
@property
def scenario_images(self):
- """
- :return: a scenario with name and uuid of images
- """
+ """:return: a scenario with name and uuid of images"""
if not CONF.service_available.glance:
return []
if not hasattr(self, '_scenario_images'):
@@ -143,9 +140,7 @@
@property
def scenario_flavors(self):
- """
- :return: a scenario with name and uuid of flavors
- """
+ """:return: a scenario with name and uuid of flavors"""
if not hasattr(self, '_scenario_flavors'):
try:
flavors = self.flavors_client.list_flavors()['flavors']
@@ -160,10 +155,11 @@
def load_tests_input_scenario_utils(*args):
+ """Wrapper for testscenarios to set the scenarios
+
+ The purpose is to avoid running a getattr on the CONF object at import.
"""
- Wrapper for testscenarios to set the scenarios to avoid running a getattr
- on the CONF object at import.
- """
+
if getattr(args[0], 'suiteClass', None) is not None:
loader, standard_tests, pattern = args
else:
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index 2ac3fb2..004c0de 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -40,10 +40,7 @@
class BaremetalClient(service_client.ServiceClient):
- """
- Base Tempest REST client for Ironic API.
-
- """
+ """Base Tempest REST client for Ironic API."""
uri_prefix = ''
@@ -58,8 +55,7 @@
return json.loads(object_str)
def _get_uri(self, resource_name, uuid=None, permanent=False):
- """
- Get URI for a specific resource or object.
+ """Get URI for a specific resource or object.
:param resource_name: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
@@ -73,8 +69,7 @@
uuid='/%s' % uuid if uuid else '')
def _make_patch(self, allowed_attributes, **kw):
- """
- Create a JSON patch according to RFC 6902.
+ """Create a JSON patch according to RFC 6902.
:param allowed_attributes: An iterable object that contains a set of
allowed attributes for an object.
@@ -103,8 +98,7 @@
return patch
def _list_request(self, resource, permanent=False, **kwargs):
- """
- Get the list of objects of the specified type.
+ """Get the list of objects of the specified type.
:param resource: The name of the REST resource, e.g., 'nodes'.
"param **kw: Parameters for the request.
@@ -122,8 +116,7 @@
return resp, self.deserialize(body)
def _show_request(self, resource, uuid, permanent=False, **kwargs):
- """
- Gets a specific object of the specified type.
+ """Gets a specific object of the specified type.
:param uuid: Unique identifier of the object in UUID format.
:return: Serialized object as a dictionary.
@@ -139,8 +132,7 @@
return resp, self.deserialize(body)
def _create_request(self, resource, object_dict):
- """
- Create an object of the specified type.
+ """Create an object of the specified type.
:param resource: The name of the REST resource, e.g., 'nodes'.
:param object_dict: A Python dict that represents an object of the
@@ -158,8 +150,7 @@
return resp, self.deserialize(body)
def _delete_request(self, resource, uuid):
- """
- Delete specified object.
+ """Delete specified object.
:param resource: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
@@ -173,8 +164,7 @@
return resp, body
def _patch_request(self, resource, uuid, patch_object):
- """
- Update specified object with JSON-patch.
+ """Update specified object with JSON-patch.
:param resource: The name of the REST resource, e.g., 'nodes'.
:param uuid: The unique identifier of an object in UUID format.
@@ -197,8 +187,7 @@
@handle_errors
def get_version_description(self, version='v1'):
- """
- Retrieves the desctription of the API.
+ """Retrieves the desctription of the API.
:param version: The version of the API. Default: 'v1'.
:return: Serialized description of API resources.
@@ -207,10 +196,7 @@
return self._list_request(version, permanent=True)
def _put_request(self, resource, put_object):
- """
- Update specified object with JSON-patch.
-
- """
+ """Update specified object with JSON-patch."""
uri = self._get_uri(resource)
put_body = json.dumps(put_object)
diff --git a/tempest/services/baremetal/v1/json/baremetal_client.py b/tempest/services/baremetal/v1/json/baremetal_client.py
index 479402a..f24ef68 100644
--- a/tempest/services/baremetal/v1/json/baremetal_client.py
+++ b/tempest/services/baremetal/v1/json/baremetal_client.py
@@ -14,9 +14,7 @@
class BaremetalClient(base.BaremetalClient):
- """
- Base Tempest REST client for Ironic API v1.
- """
+ """Base Tempest REST client for Ironic API v1."""
version = '1'
uri_prefix = 'v1'
@@ -62,8 +60,7 @@
@base.handle_errors
def show_node(self, uuid):
- """
- Gets a specific node.
+ """Gets a specific node.
:param uuid: Unique identifier of the node in UUID format.
:return: Serialized node as a dictionary.
@@ -73,8 +70,7 @@
@base.handle_errors
def show_node_by_instance_uuid(self, instance_uuid):
- """
- Gets a node associated with given instance uuid.
+ """Gets a node associated with given instance uuid.
:param uuid: Unique identifier of the node in UUID format.
:return: Serialized node as a dictionary.
@@ -88,8 +84,7 @@
@base.handle_errors
def show_chassis(self, uuid):
- """
- Gets a specific chassis.
+ """Gets a specific chassis.
:param uuid: Unique identifier of the chassis in UUID format.
:return: Serialized chassis as a dictionary.
@@ -99,8 +94,7 @@
@base.handle_errors
def show_port(self, uuid):
- """
- Gets a specific port.
+ """Gets a specific port.
:param uuid: Unique identifier of the port in UUID format.
:return: Serialized port as a dictionary.
@@ -110,8 +104,7 @@
@base.handle_errors
def show_port_by_address(self, address):
- """
- Gets a specific port by address.
+ """Gets a specific port by address.
:param address: MAC address of the port.
:return: Serialized port as a dictionary.
@@ -122,8 +115,7 @@
return self._show_request('ports', uuid=None, uri=uri)
def show_driver(self, driver_name):
- """
- Gets a specific driver.
+ """Gets a specific driver.
:param driver_name: Name of driver.
:return: Serialized driver as a dictionary.
@@ -132,8 +124,7 @@
@base.handle_errors
def create_node(self, chassis_id=None, **kwargs):
- """
- Create a baremetal node with the specified parameters.
+ """Create a baremetal node with the specified parameters.
:param cpu_arch: CPU architecture of the node. Default: x86_64.
:param cpus: Number of CPUs. Default: 8.
@@ -154,8 +145,7 @@
@base.handle_errors
def create_chassis(self, **kwargs):
- """
- Create a chassis with the specified parameters.
+ """Create a chassis with the specified parameters.
:param description: The description of the chassis.
Default: test-chassis
@@ -168,8 +158,7 @@
@base.handle_errors
def create_port(self, node_id, **kwargs):
- """
- Create a port with the specified parameters.
+ """Create a port with the specified parameters.
:param node_id: The ID of the node which owns the port.
:param address: MAC address of the port.
@@ -191,8 +180,7 @@
@base.handle_errors
def delete_node(self, uuid):
- """
- Deletes a node having the specified UUID.
+ """Deletes a node having the specified UUID.
:param uuid: The unique identifier of the node.
:return: A tuple with the server response and the response body.
@@ -202,8 +190,7 @@
@base.handle_errors
def delete_chassis(self, uuid):
- """
- Deletes a chassis having the specified UUID.
+ """Deletes a chassis having the specified UUID.
:param uuid: The unique identifier of the chassis.
:return: A tuple with the server response and the response body.
@@ -213,8 +200,7 @@
@base.handle_errors
def delete_port(self, uuid):
- """
- Deletes a port having the specified UUID.
+ """Deletes a port having the specified UUID.
:param uuid: The unique identifier of the port.
:return: A tuple with the server response and the response body.
@@ -224,8 +210,7 @@
@base.handle_errors
def update_node(self, uuid, **kwargs):
- """
- Update the specified node.
+ """Update the specified node.
:param uuid: The unique identifier of the node.
:return: A tuple with the server response and the updated node.
@@ -244,8 +229,7 @@
@base.handle_errors
def update_chassis(self, uuid, **kwargs):
- """
- Update the specified chassis.
+ """Update the specified chassis.
:param uuid: The unique identifier of the chassis.
:return: A tuple with the server response and the updated chassis.
@@ -258,8 +242,7 @@
@base.handle_errors
def update_port(self, uuid, patch):
- """
- Update the specified port.
+ """Update the specified port.
:param uuid: The unique identifier of the port.
:param patch: List of dicts representing json patches.
@@ -271,8 +254,7 @@
@base.handle_errors
def set_node_power_state(self, node_uuid, state):
- """
- Set power state of the specified node.
+ """Set power state of the specified node.
:param node_uuid: The unique identifier of the node.
:state: desired state to set (on/off/reboot).
@@ -284,8 +266,7 @@
@base.handle_errors
def validate_driver_interface(self, node_uuid):
- """
- Get all driver interfaces of a specific node.
+ """Get all driver interfaces of a specific node.
:param uuid: Unique identifier of the node in UUID format.
@@ -300,8 +281,7 @@
@base.handle_errors
def set_node_boot_device(self, node_uuid, boot_device, persistent=False):
- """
- Set the boot device of the specified node.
+ """Set the boot device of the specified node.
:param node_uuid: The unique identifier of the node.
:param boot_device: The boot device name.
@@ -318,8 +298,7 @@
@base.handle_errors
def get_node_boot_device(self, node_uuid):
- """
- Get the current boot device of the specified node.
+ """Get the current boot device of the specified node.
:param node_uuid: The unique identifier of the node.
@@ -331,8 +310,7 @@
@base.handle_errors
def get_node_supported_boot_devices(self, node_uuid):
- """
- Get the supported boot devices of the specified node.
+ """Get the supported boot devices of the specified node.
:param node_uuid: The unique identifier of the node.
@@ -344,8 +322,7 @@
@base.handle_errors
def get_console(self, node_uuid):
- """
- Get connection information about the console.
+ """Get connection information about the console.
:param node_uuid: Unique identifier of the node in UUID format.
@@ -357,8 +334,7 @@
@base.handle_errors
def set_console_mode(self, node_uuid, enabled):
- """
- Start and stop the node console.
+ """Start and stop the node console.
:param node_uuid: Unique identifier of the node in UUID format.
:param enabled: Boolean value; whether to enable or disable the
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index bedb9ec..e117719 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -88,8 +88,8 @@
return self.connect_method(**self.connection_data)
def get_aws_credentials(self, identity_client):
- """
- Obtain existing, or create new AWS credentials
+ """Obtain existing, or create new AWS credentials
+
:param identity_client: identity client with embedded credentials
:return: EC2 credentials
"""
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index e54cfe4..90b7a2d 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -160,8 +160,8 @@
return service_client.ResponseBody(resp, body)
def delete_password(self, server_id):
- """
- Removes the encrypted server password from the metadata server
+ """Removes the encrypted server password from the metadata server
+
Note that this does not actually change the instance server
password.
"""
@@ -177,6 +177,7 @@
def rebuild_server(self, server_id, image_ref, **kwargs):
"""Rebuilds a server with a new image.
+
Most parameters except the following are passed to the API without
any changes.
:param disk_config: The name is changed to OS-DCF:diskConfig
@@ -193,6 +194,7 @@
def resize_server(self, server_id, flavor_ref, **kwargs):
"""Changes the flavor of a server.
+
Most parameters except the following are passed to the API without
any changes.
:param disk_config: The name is changed to OS-DCF:diskConfig
@@ -368,9 +370,7 @@
**kwargs)
def list_virtual_interfaces(self, server_id):
- """
- List the virtual interfaces used in an instance.
- """
+ """List the virtual interfaces used in an instance."""
resp, body = self.get('/'.join(['servers', server_id,
'os-virtual-interfaces']))
body = json.loads(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 cba4c42..5aa2622 100644
--- a/tempest/services/data_processing/v1_1/data_processing_client.py
+++ b/tempest/services/data_processing/v1_1/data_processing_client.py
@@ -20,8 +20,7 @@
class DataProcessingClient(service_client.ServiceClient):
def _request_and_check_resp(self, request_func, uri, resp_status):
- """Make a request using specified request_func and check response
- status code.
+ """Make a request and check response status code.
It returns a ResponseBody.
"""
@@ -30,8 +29,7 @@
return service_client.ResponseBody(resp, body)
def _request_and_check_resp_data(self, request_func, uri, resp_status):
- """Make a request using specified request_func and check response
- status code.
+ """Make a request and check response status code.
It returns pair: resp and response data.
"""
@@ -41,8 +39,7 @@
def _request_check_and_parse_resp(self, request_func, uri,
resp_status, *args, **kwargs):
- """Make a request using specified request_func, check response status
- code and parse response body.
+ """Make a request, check response status code and parse response body.
It returns a ResponseBody.
"""
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 1c1bfaa..b27f036 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -46,8 +46,8 @@
return service_client.ResponseBody(resp, body)
def create_tenant(self, name, **kwargs):
- """
- Create a tenant
+ """Create a tenant
+
name (required): New tenant name
description: Description of new tenant (default is none)
enabled <true|false>: Initial tenant status (default is true)
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index 7af6209..3dbfe5e 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -13,6 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+"""
+http://developer.openstack.org/api-ref-identity-v3.html#service-catalog-v3
+"""
+
from oslo_serialization import jsonutils as json
from tempest.common import service_client
@@ -22,17 +26,12 @@
api_version = "v3"
def update_service(self, service_id, **kwargs):
- """Updates a service."""
- body = self.show_service(service_id)['service']
- name = kwargs.get('name', body['name'])
- type = kwargs.get('type', body['type'])
- desc = kwargs.get('description', body['description'])
- patch_body = {
- 'description': desc,
- 'type': type,
- 'name': name
- }
- patch_body = json.dumps({'service': patch_body})
+ """Updates a service.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#updateService
+ """
+ patch_body = json.dumps({'service': kwargs})
resp, body = self.patch('services/%s' % service_id, patch_body)
self.expected_success(200, resp.status)
body = json.loads(body)
@@ -46,15 +45,13 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def create_service(self, serv_type, name=None, description=None,
- enabled=True):
- body_dict = {
- 'name': name,
- 'type': serv_type,
- 'enabled': enabled,
- 'description': description,
- }
- body = json.dumps({'service': body_dict})
+ def create_service(self, **kwargs):
+ """Creates a service.
+
+ Available params: see http://developer.openstack.org/
+ api-ref-identity-v3.html#createService
+ """
+ body = json.dumps({'service': kwargs})
resp, body = self.post("services", body)
self.expected_success(201, resp.status)
body = json.loads(body)
diff --git a/tempest/services/network/json/base.py b/tempest/services/network/json/base.py
index fe150df..6ebc245 100644
--- a/tempest/services/network/json/base.py
+++ b/tempest/services/network/json/base.py
@@ -18,9 +18,10 @@
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.
+ """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'
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index d811c51..50a5d5e 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -21,9 +21,10 @@
class NetworkClient(base.BaseNetworkClient):
- """
- Tempest REST client for Neutron. Uses v2 of the Neutron API, since the
- V1 API has been removed from the code base.
+ """Tempest REST client for Neutron.
+
+ Uses v2 of the Neutron API, since the V1 API has been removed from the
+ code base.
Implements create, delete, update, list and show for the basic Neutron
abstractions (networks, sub-networks, routers, ports and floating IP):
@@ -177,8 +178,8 @@
def wait_for_resource_status(self, fetch, status, interval=None,
timeout=None):
- """
- @summary: Waits for a network resource to reach a status
+ """Waits for a network resource to reach a status
+
@param fetch: the callable to be used to query the resource status
@type fecth: callable that takes no parameters and returns the resource
@param status: the status that the resource has to reach
@@ -313,7 +314,8 @@
return self.list_resources(uri)
def update_agent(self, agent_id, agent_info):
- """
+ """Update agent
+
:param agent_info: Agent update information.
E.g {"admin_state_up": True}
"""
diff --git a/tempest/services/network/resources.py b/tempest/services/network/resources.py
index ae30312..10911f7 100644
--- a/tempest/services/network/resources.py
+++ b/tempest/services/network/resources.py
@@ -19,10 +19,7 @@
class AttributeDict(dict):
-
- """
- Provide attribute access (dict.key) to dictionary values.
- """
+ """Provide attribute access (dict.key) to dictionary values."""
def __getattr__(self, name):
"""Allow attribute access for all keys in the dict."""
@@ -33,10 +30,9 @@
@six.add_metaclass(abc.ABCMeta)
class DeletableResource(AttributeDict):
+ """Support deletion of neutron resources (networks, subnets)
- """
- Support deletion of neutron resources (networks, subnets) via a
- delete() method, as is supported by keystone and nova resources.
+ via a delete() method, as is supported by keystone and nova resources.
"""
def __init__(self, *args, **kwargs):
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index d89aa5d..2c7fe29 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -59,8 +59,8 @@
return resp, body
def list_account_metadata(self):
- """
- HEAD on the storage URL
+ """HEAD on the storage URL
+
Returns all account metadata headers
"""
resp, body = self.head('')
@@ -86,9 +86,7 @@
def delete_account_metadata(self, metadata,
metadata_prefix='X-Remove-Account-Meta-'):
- """
- Deletes an account metadata entry.
- """
+ """Deletes an account metadata entry."""
headers = {}
for item in metadata:
@@ -103,9 +101,7 @@
delete_metadata=None,
create_metadata_prefix='X-Account-Meta-',
delete_metadata_prefix='X-Remove-Account-Meta-'):
- """
- Creates and deletes an account metadata entry.
- """
+ """Creates and deletes an account metadata entry."""
headers = {}
for key in create_metadata:
headers[create_metadata_prefix + key] = create_metadata[key]
@@ -117,8 +113,8 @@
return resp, body
def list_account_containers(self, params=None):
- """
- GET on the (base) storage URL
+ """GET on the (base) storage URL
+
Given valid X-Auth-Token, returns a list of all containers for the
account.
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index e8ee20b..73c25db 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -29,9 +29,9 @@
remove_metadata=None,
metadata_prefix='X-Container-Meta-',
remove_metadata_prefix='X-Remove-Container-Meta-'):
- """
- Creates a container, with optional metadata passed in as a
- dictionary
+ """Creates a container
+
+ with optional metadata passed in as a dictionary
"""
url = str(container_name)
headers = {}
@@ -90,19 +90,17 @@
return resp, body
def list_container_metadata(self, container_name):
- """
- Retrieves container metadata headers
- """
+ """Retrieves container metadata headers"""
url = str(container_name)
resp, body = self.head(url)
self.expected_success(204, resp.status)
return resp, body
def list_all_container_objects(self, container, params=None):
- """
- Returns complete list of all objects in the container, even if
- item count is beyond 10,000 item listing limit.
- Does not require any parameters aside from container name.
+ """Returns complete list of all objects in the container
+
+ even if item count is beyond 10,000 item listing limit.
+ Does not require any parameters aside from container name.
"""
# TODO(dwalleck): Rewrite using json format to avoid newlines at end of
# obj names. Set limit to API limit - 1 (max returned items = 9999)
@@ -121,8 +119,7 @@
return objlist
def list_container_contents(self, container, params=None):
- """
- List the objects in a container, given the container name
+ """List the objects in a container, given the container name
Returns the container object listing as a plain text list, or as
xml or json if that option is specified via the 'format' argument.
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 2265587..5890e33 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -149,9 +149,7 @@
return resp, body
def put_object_with_chunk(self, container, name, contents, chunk_size):
- """
- Put an object with Transfer-Encoding header
- """
+ """Put an object with Transfer-Encoding header"""
if self.base_url is None:
self._set_auth()
@@ -204,8 +202,8 @@
def put_object_connection(base_url, container, name, contents=None,
chunk_size=65536, headers=None, query_string=None):
- """
- Helper function to make connection to put object with httplib
+ """Helper function to make connection to put object with httplib
+
:param base_url: base_url of an object client
:param container: container name that the object is in
:param name: object name to put
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/json/admin/volume_hosts_client.py
index ab9cd5a..939db59 100644
--- a/tempest/services/volume/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/json/admin/volume_hosts_client.py
@@ -20,9 +20,7 @@
class BaseVolumeHostsClient(service_client.ServiceClient):
- """
- Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume Hosts API requests"""
def list_hosts(self, params=None):
"""Lists all hosts."""
@@ -38,6 +36,4 @@
class VolumeHostsClient(BaseVolumeHostsClient):
- """
- Client class to send CRUD Volume Host API V1 requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume Host API V1 requests"""
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py
index 207554d..f6d4a14 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/json/admin/volume_quotas_client.py
@@ -19,9 +19,7 @@
class BaseVolumeQuotasClient(service_client.ServiceClient):
- """
- Client class to send CRUD Volume Quotas API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume Quotas API requests"""
TYPE = "json"
@@ -79,6 +77,4 @@
class VolumeQuotasClient(BaseVolumeQuotasClient):
- """
- Client class to send CRUD Volume Type API V1 requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume Type API V1 requests"""
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index cd61859..f2da8a5 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -21,9 +21,7 @@
class BaseVolumeTypesClient(service_client.ServiceClient):
- """
- Client class to send CRUD Volume Types API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume Types API requests"""
def is_resource_deleted(self, resource):
# to use this method self.resource must be defined to respective value
@@ -69,8 +67,8 @@
return service_client.ResponseBody(resp, body)
def create_volume_type(self, name, **kwargs):
- """
- Creates a new Volume_type.
+ """Creates a new Volume_type.
+
name(Required): Name of volume_type.
Following optional keyword arguments are accepted:
extra_specs: A dictionary of values to be used as extra_specs.
@@ -113,8 +111,8 @@
return service_client.ResponseBody(resp, body)
def create_volume_type_extra_specs(self, vol_type_id, extra_spec):
- """
- Creates a new Volume_type extra spec.
+ """Creates a new Volume_type extra spec.
+
vol_type_id: Id of volume_type.
extra_specs: A dictionary of values to be used as extra_specs.
"""
@@ -134,8 +132,8 @@
def update_volume_type_extra_specs(self, vol_type_id, extra_spec_name,
extra_spec):
- """
- Update a volume_type extra spec.
+ """Update a volume_type extra spec.
+
vol_type_id: Id of volume_type.
extra_spec_name: Name of the extra spec to be updated.
extra_spec: A dictionary of with key as extra_spec_name and the
@@ -150,8 +148,8 @@
return service_client.ResponseBody(resp, body)
def show_encryption_type(self, vol_type_id):
- """
- Get the volume encryption type for the specified volume type.
+ """Get the volume encryption type for the specified volume type.
+
vol_type_id: Id of volume_type.
"""
url = "/types/%s/encryption" % str(vol_type_id)
@@ -161,8 +159,7 @@
return service_client.ResponseBody(resp, body)
def create_encryption_type(self, vol_type_id, **kwargs):
- """
- Create a new encryption type for the specified volume type.
+ """Create a new encryption type for the specified volume type.
vol_type_id: Id of volume_type.
provider: Class providing encryption support.
diff --git a/tempest/services/volume/json/availability_zone_client.py b/tempest/services/volume/json/availability_zone_client.py
index 4d24ede..36f95d6 100644
--- a/tempest/services/volume/json/availability_zone_client.py
+++ b/tempest/services/volume/json/availability_zone_client.py
@@ -28,6 +28,4 @@
class VolumeAvailabilityZoneClient(BaseVolumeAvailabilityZoneClient):
- """
- Volume V1 availability zone client.
- """
+ """Volume V1 availability zone client."""
diff --git a/tempest/services/volume/json/backups_client.py b/tempest/services/volume/json/backups_client.py
index 6827c93..3045992 100644
--- a/tempest/services/volume/json/backups_client.py
+++ b/tempest/services/volume/json/backups_client.py
@@ -24,9 +24,7 @@
class BaseBackupsClient(service_client.ServiceClient):
- """
- Client class to send CRUD Volume backup API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume backup API requests"""
def create_backup(self, volume_id, container=None, name=None,
description=None):
diff --git a/tempest/services/volume/json/extensions_client.py b/tempest/services/volume/json/extensions_client.py
index 5744d4a..d7d3197 100644
--- a/tempest/services/volume/json/extensions_client.py
+++ b/tempest/services/volume/json/extensions_client.py
@@ -29,6 +29,4 @@
class ExtensionsClient(BaseExtensionsClient):
- """
- Volume V1 extensions client.
- """
+ """Volume V1 extensions client."""
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 3fcf18c..77c9dd1 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -51,8 +51,8 @@
return service_client.ResponseBody(resp, body)
def create_snapshot(self, volume_id, **kwargs):
- """
- Creates a new snapshot.
+ """Creates a new snapshot.
+
volume_id(Required): id of the volume.
force: Create a snapshot even if the volume attached (Default=False)
display_name: Optional snapshot Name.
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index 9304f63..c2a76f0 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -23,9 +23,7 @@
class BaseVolumesClient(service_client.ServiceClient):
- """
- Base client class to send CRUD Volume API requests to a Cinder endpoint
- """
+ """Base client class to send CRUD Volume API requests"""
create_resp = 200
@@ -74,8 +72,8 @@
return service_client.ResponseBody(resp, body)
def create_volume(self, size=None, **kwargs):
- """
- Creates a new Volume.
+ """Creates a new Volume.
+
size: Size of volume in GB.
Following optional keyword arguments are accepted:
display_name: Optional Volume Name(only for V1).
@@ -339,6 +337,4 @@
class VolumesClient(BaseVolumesClient):
- """
- Client class to send CRUD Volume V1 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V1 API requests"""
diff --git a/tempest/services/volume/v2/json/admin/volume_hosts_client.py b/tempest/services/volume/v2/json/admin/volume_hosts_client.py
index f0cc03f..649c9ec 100644
--- a/tempest/services/volume/v2/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/v2/json/admin/volume_hosts_client.py
@@ -18,7 +18,5 @@
class VolumeHostsV2Client(volume_hosts_client.BaseVolumeHostsClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_quotas_client.py b/tempest/services/volume/v2/json/admin/volume_quotas_client.py
index 635b6e1..80fffc7 100644
--- a/tempest/services/volume/v2/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/v2/json/admin/volume_quotas_client.py
@@ -17,7 +17,5 @@
class VolumeQuotasV2Client(volume_quotas_client.BaseVolumeQuotasClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_services_client.py b/tempest/services/volume/v2/json/admin/volume_services_client.py
index d0efc38..88eb82f 100644
--- a/tempest/services/volume/v2/json/admin/volume_services_client.py
+++ b/tempest/services/volume/v2/json/admin/volume_services_client.py
@@ -17,7 +17,5 @@
class VolumesServicesV2Client(vs_cli.BaseVolumesServicesClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/admin/volume_types_client.py b/tempest/services/volume/v2/json/admin/volume_types_client.py
index 1b9ff51..78fe8e5 100644
--- a/tempest/services/volume/v2/json/admin/volume_types_client.py
+++ b/tempest/services/volume/v2/json/admin/volume_types_client.py
@@ -18,7 +18,5 @@
class VolumeTypesV2Client(volume_types_client.BaseVolumeTypesClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/backups_client.py b/tempest/services/volume/v2/json/backups_client.py
index 1ce11ce..8e87505 100644
--- a/tempest/services/volume/v2/json/backups_client.py
+++ b/tempest/services/volume/v2/json/backups_client.py
@@ -17,7 +17,5 @@
class BackupsClientV2(backups_client.BaseBackupsClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
diff --git a/tempest/services/volume/v2/json/volumes_client.py b/tempest/services/volume/v2/json/volumes_client.py
index a6d081c..a56a7be 100644
--- a/tempest/services/volume/v2/json/volumes_client.py
+++ b/tempest/services/volume/v2/json/volumes_client.py
@@ -17,8 +17,6 @@
class VolumesV2Client(volumes_client.BaseVolumesClient):
- """
- Client class to send CRUD Volume V2 API requests to a Cinder endpoint
- """
+ """Client class to send CRUD Volume V2 API requests"""
api_version = "v2"
create_resp = 202
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index 66d2b36..993359d 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -16,14 +16,14 @@
from oslo_log import log as logging
-from tempest import clients
+from tempest.common import credentials_factory as credentials
from tempest.common import waiters
LOG = logging.getLogger(__name__)
def cleanup():
- admin_manager = clients.AdminManager()
+ admin_manager = credentials.AdminManager()
body = admin_manager.servers_client.list_servers(all_tenants=True)
LOG.info("Cleanup::remove %s servers" % len(body['servers']))
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 7634d2c..eec52cb 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -26,6 +26,7 @@
from tempest import clients
from tempest.common import cred_client
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
@@ -122,7 +123,7 @@
"""
Workload driver. Executes an action function against a nova-cluster.
"""
- admin_manager = clients.AdminManager()
+ admin_manager = credentials.AdminManager()
ssh_user = CONF.stress.target_ssh_user
ssh_key = CONF.stress.target_private_key_path
@@ -145,7 +146,7 @@
if test.get('use_admin', False):
manager = admin_manager
else:
- manager = clients.Manager()
+ manager = credentials.ConfiguredUserManager()
for p_number in moves.xrange(test.get('threads', default_thread_num)):
if test.get('use_isolated_tenants', False):
username = data_utils.rand_name("stress_user")
diff --git a/tempest/test.py b/tempest/test.py
index b8ba5f4..4be6779 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -32,7 +32,7 @@
from tempest import clients
from tempest.common import cred_client
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest.common import fixed_network
import tempest.common.generator.valid_generator as valid
import tempest.common.validation_resources as vresources
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index a53ed5f..75401db 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -15,7 +15,7 @@
from oslo_config import cfg
from oslotest import mockpatch
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest.tests import base
from tempest.tests import fake_config
diff --git a/tempest/tests/common/test_alt_available.py b/tempest/tests/common/test_alt_available.py
index 6a86f73..db3f5ec 100644
--- a/tempest/tests/common/test_alt_available.py
+++ b/tempest/tests/common/test_alt_available.py
@@ -15,7 +15,7 @@
from oslo_config import cfg
from oslotest import mockpatch
-from tempest.common import credentials
+from tempest.common import credentials_factory as credentials
from tempest import config
from tempest.tests import base
from tempest.tests import fake_config
diff --git a/tempest/tests/common/test_cred_provider.py b/tempest/tests/common/test_configured_creds.py
similarity index 95%
rename from tempest/tests/common/test_cred_provider.py
rename to tempest/tests/common/test_configured_creds.py
index d404660..96b75fd 100644
--- a/tempest/tests/common/test_cred_provider.py
+++ b/tempest/tests/common/test_configured_creds.py
@@ -18,8 +18,7 @@
from tempest_lib.services.identity.v2 import token_client as v2_client
from tempest_lib.services.identity.v3 import token_client as v3_client
-
-from tempest.common import cred_provider
+from tempest.common import credentials_factory as common_creds
from tempest.common import tempest_fixtures as fixtures
from tempest import config
from tempest.tests import base
@@ -65,12 +64,12 @@
def _verify_credentials(self, credentials_class, filled=True,
identity_version=None):
- for ctype in cred_provider.CREDENTIAL_TYPES:
+ for ctype in common_creds.CREDENTIAL_TYPES:
if identity_version is None:
- creds = cred_provider.get_configured_credentials(
+ creds = common_creds.get_configured_credentials(
credential_type=ctype, fill_in=filled)
else:
- creds = cred_provider.get_configured_credentials(
+ creds = common_creds.get_configured_credentials(
credential_type=ctype, fill_in=filled,
identity_version=identity_version)
self._check(creds, credentials_class, filled)
diff --git a/tempest/tests/common/test_credentials.py b/tempest/tests/common/test_credentials.py
new file mode 100644
index 0000000..136ac02
--- /dev/null
+++ b/tempest/tests/common/test_credentials.py
@@ -0,0 +1,36 @@
+# Copyright 2015 Hewlett-Packard Development Company, L.P.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.common import credentials_factory as credentials
+from tempest import config
+from tempest import exceptions
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class TestLegacyCredentialsProvider(base.TestCase):
+
+ fixed_params = {'identity_version': 'v2'}
+
+ def setUp(self):
+ super(TestLegacyCredentialsProvider, self).setUp()
+ self.useFixture(fake_config.ConfigFixture())
+ self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+
+ def test_get_creds_roles_legacy_invalid(self):
+ test_accounts_class = credentials.LegacyCredentialProvider(
+ **self.fixed_params)
+ self.assertRaises(exceptions.InvalidConfiguration,
+ test_accounts_class.get_creds_by_roles,
+ ['fake_role'])
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/common/test_dynamic_creds.py
index 73e180e..78064a7 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/common/test_dynamic_creds.py
@@ -17,6 +17,7 @@
from oslotest import mockpatch
from tempest_lib.services.identity.v2 import token_client as json_token_client
+from tempest.common import credentials_factory as credentials
from tempest.common import dynamic_creds
from tempest.common import service_client
from tempest import config
@@ -46,6 +47,8 @@
cfg.CONF.set_default('operator_role', 'FakeRole',
group='object-storage')
self._mock_list_ec2_credentials('fake_user_id', 'fake_tenant_id')
+ self.fixed_params.update(
+ admin_creds=self._get_fake_admin_creds())
def test_tempest_client(self):
creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
@@ -54,6 +57,13 @@
self.assertTrue(isinstance(creds.network_admin_client,
json_network_client.NetworkClient))
+ def _get_fake_admin_creds(self):
+ return credentials.get_credentials(
+ fill_in=False,
+ identity_version=self.fixed_params['identity_version'],
+ username='fake_username', password='fake_password',
+ tenant_name='fake_tenant')
+
def _mock_user_create(self, id, name):
user_fix = self.useFixture(mockpatch.PatchObject(
json_iden_client.IdentityClient,
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/common/test_preprov_creds.py
index 8a014af..36dd976 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/common/test_preprov_creds.py
@@ -329,36 +329,3 @@
self.assertIn('id', network)
self.assertEqual('fake-id', network['id'])
self.assertEqual('network-2', network['name'])
-
-
-class TestNotLockingAccount(base.TestCase):
-
- fixed_params = {'name': 'test class',
- 'identity_version': 'v2',
- 'admin_role': 'admin'}
-
- def setUp(self):
- super(TestNotLockingAccount, self).setUp()
- self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
- self.useFixture(lockutils_fixtures.ExternalLockFixture())
- self.test_accounts = [
- {'username': 'test_user1', 'tenant_name': 'test_tenant1',
- 'password': 'p'},
- {'username': 'test_user2', 'tenant_name': 'test_tenant2',
- 'password': 'p'},
- {'username': 'test_user3', 'tenant_name': 'test_tenant3',
- 'password': 'p'},
- ]
- self.useFixture(mockpatch.Patch(
- 'tempest.common.preprov_creds.read_accounts_yaml',
- return_value=self.test_accounts))
- cfg.CONF.set_default('test_accounts_file', '', group='auth')
- self.useFixture(mockpatch.Patch('os.path.isfile', return_value=True))
-
- def test_get_creds_roles_nonlocking_invalid(self):
- test_accounts_class = preprov_creds.NonLockingCredentialProvider(
- **self.fixed_params)
- self.assertRaises(exceptions.InvalidConfiguration,
- test_accounts_class.get_creds_by_roles,
- ['fake_role'])
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 1ced180..05c47bb 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -27,7 +27,7 @@
from six.moves.urllib import parse as urlparse
from tempest_lib import exceptions as lib_exc
-import tempest.clients
+from tempest.common import credentials_factory as credentials
from tempest.common.utils import file_utils
from tempest import config
from tempest import exceptions
@@ -67,7 +67,7 @@
raise Exception("Unknown (Authentication?) Error")
# NOTE(andreaf) Setting up an extra manager here is redundant,
# and should be removed.
- openstack = tempest.clients.Manager()
+ openstack = credentials.ConfiguredUserManager()
try:
if urlparse.urlparse(CONF.boto.ec2_url).hostname is None:
raise Exception("Failed to get hostname from the ec2_url")
diff --git a/tools/check_uuid.py b/tools/check_uuid.py
index e21c3d8..a71ad39 100755
--- a/tools/check_uuid.py
+++ b/tools/check_uuid.py
@@ -114,10 +114,8 @@
@staticmethod
def _get_idempotent_id(test_node):
- """
- Return key-value dict with all metadata from @test.idempotent_id
- decorators for test method
- """
+ # Return key-value dict with all metadata from @test.idempotent_id
+ # decorators for test method
idempotent_id = None
for decorator in test_node.decorator_list:
if (hasattr(decorator, 'func') and
@@ -264,8 +262,9 @@
return self._filter_tests(check_uuid_in_meta, tests)
def report_collisions(self, tests):
- """Reports collisions if there are any. Returns true if
- collisions exist.
+ """Reports collisions if there are any.
+
+ Returns true if collisions exist.
"""
uuids = {}
@@ -298,8 +297,9 @@
return bool(self._filter_tests(report, tests))
def report_untagged(self, tests):
- """Reports untagged tests if there are any. Returns true if
- untagged tests exist.
+ """Reports untagged tests if there are any.
+
+ Returns true if untagged tests exist.
"""
def report(module_name, test_name, tests):
error_str = "%s:%s\nmissing @test.idempotent_id('...')\n%s\n" % (
@@ -312,9 +312,7 @@
return bool(self._filter_tests(report, tests))
def fix_tests(self, tests):
- """Add uuids to all tests specified in tests and
- fix it in source files
- """
+ """Add uuids to all tests specified in tests and fix it"""
patcher = SourcePatcher()
for module_name in tests:
add_import_once = True
diff --git a/tools/colorizer.py b/tools/colorizer.py
index e7152f2..3f68a51 100755
--- a/tools/colorizer.py
+++ b/tools/colorizer.py
@@ -50,9 +50,9 @@
class _AnsiColorizer(object):
- """
- A colorizer is an object that loosely wraps around a stream, allowing
- callers to write text to the stream in a particular color.
+ """A colorizer is an object that loosely wraps around a stream
+
+ allowing callers to write text to the stream in a particular color.
Colorizer classes must implement C{supported()} and C{write(text, color)}.
"""
@@ -63,7 +63,8 @@
self.stream = stream
def supported(cls, stream=sys.stdout):
- """
+ """Check the current platform supports coloring terminal output
+
A class method that returns True if the current platform supports
coloring terminal output using this method. Returns False otherwise.
"""
@@ -86,8 +87,7 @@
supported = classmethod(supported)
def write(self, text, color):
- """
- Write the given text to the stream in the given color.
+ """Write the given text to the stream in the given color.
@param text: Text to be written to the stream.
@@ -98,9 +98,7 @@
class _Win32Colorizer(object):
- """
- See _AnsiColorizer docstring.
- """
+ """See _AnsiColorizer docstring."""
def __init__(self, stream):
import win32console
red, green, blue, bold = (win32console.FOREGROUND_RED,
@@ -146,9 +144,7 @@
class _NullColorizer(object):
- """
- See _AnsiColorizer docstring.
- """
+ """See _AnsiColorizer docstring."""
def __init__(self, stream):
self.stream = stream
diff --git a/tools/skip_tracker.py b/tools/skip_tracker.py
index 50f33eb..a47e217 100755
--- a/tools/skip_tracker.py
+++ b/tools/skip_tracker.py
@@ -40,7 +40,8 @@
def find_skips(start=TESTDIR):
- """
+ """Find skipped tests
+
Returns a list of tuples (method, bug) that represent
test methods that have been decorated to skip because of
a particular bug.
@@ -67,9 +68,7 @@
def find_skips_in_file(path):
- """
- Return the skip tuples in a test file
- """
+ """Return the skip tuples in a test file"""
BUG_RE = re.compile(r'\s*@.*skip_because\(bug=[\'"](\d+)[\'"]')
DEF_RE = re.compile(r'\s*def (\w+)\(')
bug_found = False