Merge "Tool for generation user accounts from spec"
diff --git a/README.rst b/README.rst
index 94a5352..af24569 100644
--- a/README.rst
+++ b/README.rst
@@ -117,8 +117,8 @@
Tempest suite.
Alternatively, you can use the run_tests.sh script which will create a venv and
-run the unit tests. There are also the py26, py27, or py33 tox jobs which will
-run the unit tests with the corresponding version of python.
+run the unit tests. There are also the py27 and py34 tox jobs which will run
+the unit tests with the corresponding version of python.
Python 2.6
----------
@@ -131,3 +131,16 @@
on an earlier release with python 2.6 you can easily run Tempest against it
from a remote system running python 2.7. (or deploy a cloud guest in your cloud
that has python 2.7)
+
+Python 3.4
+----------
+
+Starting during the Liberty release development cycle work began on enabling
+Tempest to run under both Python 2.7 and Python 3.4. Tempest strives to fully
+support running with Python 3.4. A gating unit test job was added to also run
+Tempest's unit tests under Python 3.4. This means that the Tempest code at
+least imports under Python 3.4 and things that have unit test coverage will
+work on Python 3.4. However, because large parts of Tempest are self verifying
+there might be uncaught issues running on Python 3.4. So until there is a gating
+job which does a full Tempest run using Python 3.4 there isn't any guarantee
+that running Tempest under Python 3.4 is bug free.
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index b6e00ce..b434fdc 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -115,6 +115,8 @@
#. Provide tempest with the location of you accounts.yaml file with the
test_accounts_file option in the auth section
+ #. Set allow_tenant_isolation = False in the auth group
+
It is worth pointing out that each set of credentials in the accounts.yaml
should have a unique tenant. This is required to provide proper isolation
to the tests using the credentials, and failure to do this will likely cause
@@ -140,6 +142,11 @@
#. alt_password
#. alt_tenant_name
+And in the auth secion:
+
+ #. allow_tenant_isolation = False
+ #. comment out 'test_accounts_file' or keep it as empty
+
It only makes sense to use it if parallel execution isn't needed, since tempest
won't be able to properly isolate tests using this. Additionally, using the
traditional config options for credentials is not able to provide credentials to
diff --git a/setup.cfg b/setup.cfg
index 3159657..3a14bba 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -15,6 +15,8 @@
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.4
[entry_points]
console_scripts =
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 26d6661..c4581e5 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -52,7 +52,6 @@
def setup_credentials(cls):
cls.set_network_resources()
super(BaseComputeTest, cls).setup_credentials()
- cls.multi_user = cls.check_multi_user()
@classmethod
def setup_clients(cls):
@@ -112,14 +111,6 @@
super(BaseComputeTest, cls).resource_cleanup()
@classmethod
- def check_multi_user(cls):
- # We have a list of accounts now, so just checking if the list is gt 2
- if not cls.isolated_creds.is_multi_user():
- msg = "Not enough users available for multi-user testing"
- raise exceptions.InvalidConfiguration(msg)
- return True
-
- @classmethod
def clear_servers(cls):
LOG.debug('Clearing servers: %s', ','.join(
server['id'] for server in cls.servers))
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index 258ff1f..9f007bf 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -92,9 +92,11 @@
@classmethod
def resource_cleanup(cls):
- if cls.multi_user:
+ if hasattr(cls, 'image'):
cls.images_client.delete_image(cls.image['id'])
+ if hasattr(cls, 'keypairname'):
cls.keypairs_client.delete_keypair(cls.keypairname)
+ if hasattr(cls, 'security_group'):
cls.security_client.delete_security_group(cls.security_group['id'])
super(AuthorizationTestJSON, cls).resource_cleanup()
diff --git a/tempest/api/messaging/base.py b/tempest/api/messaging/base.py
index 2ddc3fc..34ac860 100644
--- a/tempest/api/messaging/base.py
+++ b/tempest/api/messaging/base.py
@@ -116,20 +116,6 @@
return resp, body
@classmethod
- def get_single_message(cls, message_uri):
- """Wrapper utility that gets a single message."""
- resp, body = cls.client.show_single_message(message_uri)
-
- return resp, body
-
- @classmethod
- def get_multiple_messages(cls, message_uri):
- """Wrapper utility that gets multiple messages."""
- resp, body = cls.client.show_multiple_messages(message_uri)
-
- return resp, body
-
- @classmethod
def delete_messages(cls, message_uri):
"""Wrapper utility that deletes messages."""
resp, body = cls.client.delete_messages(message_uri)
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 8bc9b12..0c7fa6b 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -15,8 +15,6 @@
from tempest_lib import exceptions as lib_exc
-from tempest import clients
-from tempest.common import credentials
from tempest.common import custom_matchers
from tempest import config
import tempest.test
@@ -38,19 +36,7 @@
cls.set_network_resources()
super(BaseObjectTest, cls).setup_credentials()
operator_role = CONF.object_storage.operator_role
- # There are no credentials by type used by object storage tests so
- # isolated_creds must still be initialized
- cls.isolated_creds = credentials.get_isolated_credentials(
- cls.__name__, network_resources=cls.network_resources)
- if not cls.isolated_creds.is_role_available(operator_role):
- skip_msg = ("%s skipped because the configured credential provider"
- " is not able to provide credentials with the %s role "
- "assigned." % (cls.__name__, operator_role))
- raise cls.skipException(skip_msg)
- else:
- # Get isolated creds for normal user
- cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
- [operator_role]))
+ cls.os = cls.get_client_manager(roles=[operator_role])
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 364d6e1..04bfee4 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -15,7 +15,6 @@
from tempest_lib.common.utils import data_utils
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -28,15 +27,8 @@
def setup_credentials(cls):
super(AccountQuotasTest, cls).setup_credentials()
reseller_admin_role = CONF.object_storage.reseller_admin_role
- if not cls.isolated_creds.is_role_available(reseller_admin_role):
- skip_msg = ("%s skipped because the configured credential provider"
- " is not able to provide credentials with the %s role "
- "assigned." % (cls.__name__, reseller_admin_role))
- raise cls.skipException(skip_msg)
- else:
- cls.os_reselleradmin = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[reseller_admin_role]))
+ cls.os_reselleradmin = cls.get_client_manager(
+ roles=[reseller_admin_role])
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index b32943c..a11b407 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -17,7 +17,6 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -30,15 +29,8 @@
def setup_credentials(cls):
super(AccountQuotasNegativeTest, cls).setup_credentials()
reseller_admin_role = CONF.object_storage.reseller_admin_role
- if not cls.isolated_creds.is_role_available(reseller_admin_role):
- skip_msg = ("%s skipped because the configured credential provider"
- " is not able to provide credentials with the %s role "
- "assigned." % (cls.__name__, reseller_admin_role))
- raise cls.skipException(skip_msg)
- else:
- cls.os_reselleradmin = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[reseller_admin_role]))
+ cls.os_reselleradmin = cls.get_client_manager(
+ roles=[reseller_admin_role])
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 918bd5a..c28a3e0 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -20,7 +20,6 @@
import testtools
from tempest.api.object_storage import base
-from tempest import clients
from tempest.common import custom_matchers
from tempest import config
from tempest import test
@@ -35,9 +34,8 @@
@classmethod
def setup_credentials(cls):
super(AccountTest, cls).setup_credentials()
- cls.os_operator = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[CONF.object_storage.operator_role], force_new=True))
+ cls.os_operator = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index feccf18..dfc5dfa 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -15,7 +15,6 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -27,9 +26,8 @@
@classmethod
def setup_credentials(cls):
super(AccountNegativeTest, cls).setup_credentials()
- cls.os_operator = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[CONF.object_storage.operator_role], force_new=True))
+ cls.os_operator = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@test.attr(type=['negative'])
@test.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 1003f82..25dac6b 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -16,7 +16,6 @@
from tempest_lib.common.utils import data_utils
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -28,9 +27,8 @@
@classmethod
def setup_credentials(cls):
super(ObjectTestACLs, cls).setup_credentials()
- cls.os_operator = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[CONF.object_storage.operator_role], force_new=True))
+ cls.os_operator = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 2c6d3cc..31c301a 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -16,7 +16,6 @@
from tempest_lib import exceptions as lib_exc
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -28,9 +27,8 @@
@classmethod
def setup_credentials(cls):
super(ObjectACLsNegativeTest, cls).setup_credentials()
- cls.os_operator = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[CONF.object_storage.operator_role], force_new=True))
+ cls.os_operator = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 53bcfa6..4c0723d 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -22,7 +22,6 @@
from tempest.api.object_storage import base
-from tempest import clients
from tempest import config
from tempest import test
@@ -41,8 +40,8 @@
@classmethod
def setup_credentials(cls):
super(ContainerSyncTest, cls).setup_credentials()
- cls.os_alt = clients.Manager(cls.isolated_creds.get_creds_by_roles(
- [CONF.object_storage.operator_role], force_new=True))
+ cls.os_alt = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 8075e91..b02f178 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -24,7 +24,6 @@
from tempest_lib.common.utils import data_utils
from tempest.api.object_storage import base
-from tempest import clients
from tempest.common import custom_matchers
from tempest import config
from tempest import test
@@ -993,9 +992,8 @@
@classmethod
def setup_credentials(cls):
super(PublicObjectTest, cls).setup_credentials()
- cls.os_alt = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- roles=[CONF.object_storage.operator_role], force_new=True))
+ cls.os_alt = cls.get_client_manager(
+ roles=[CONF.object_storage.operator_role], force_new=True)
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 35f51b9..af97794 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -17,7 +17,6 @@
from tempest_lib import exceptions as lib_exc
import yaml
-from tempest import clients
from tempest import config
import tempest.test
@@ -41,14 +40,7 @@
def setup_credentials(cls):
super(BaseOrchestrationTest, cls).setup_credentials()
stack_owner_role = CONF.orchestration.stack_owner_role
- if not cls.isolated_creds.is_role_available(stack_owner_role):
- skip_msg = ("%s skipped because the configured credential provider"
- " is not able to provide credentials with the %s role "
- "assigned." % (cls.__name__, stack_owner_role))
- raise cls.skipException(skip_msg)
- else:
- cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
- [stack_owner_role]))
+ cls.os = cls.get_client_manager(roles=[stack_owner_role])
@classmethod
def setup_clients(cls):
diff --git a/tempest/clients.py b/tempest/clients.py
index a0c9471..9f6a9bb 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -22,6 +22,7 @@
from tempest.common import cred_provider
from tempest.common import negative_rest_client
from tempest import config
+from tempest import exceptions
from tempest import manager
from tempest.services.baremetal.v1.json.baremetal_client import \
BaremetalClientJSON
@@ -343,11 +344,22 @@
self.credentials_client = CredentialsClientJSON(self.auth_provider,
**params)
# Token clients do not use the catalog. They only need default_params.
- self.token_client = TokenClientJSON(CONF.identity.uri,
- **self.default_params)
+ # They read auth_url, so they should only be set if the corresponding
+ # API version is marked as enabled
+ if CONF.identity_feature_enabled.api_v2:
+ if CONF.identity.uri:
+ self.token_client = TokenClientJSON(
+ CONF.identity.uri, **self.default_params)
+ else:
+ msg = 'Identity v2 API enabled, but no identity.uri set'
+ raise exceptions.InvalidConfiguration(msg)
if CONF.identity_feature_enabled.api_v3:
- self.token_v3_client = V3TokenClientJSON(CONF.identity.uri_v3,
- **self.default_params)
+ if CONF.identity.uri_v3:
+ self.token_v3_client = V3TokenClientJSON(
+ CONF.identity.uri_v3, **self.default_params)
+ else:
+ msg = 'Identity v3 API enabled, but no identity.uri_v3 set'
+ raise exceptions.InvalidConfiguration(msg)
def _set_volume_clients(self):
params = {
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 1ad12eb..eb6f143 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -343,6 +343,44 @@
self.data['volumes'] = vols
+class VolumeQuotaService(BaseService):
+ def __init__(self, manager, **kwargs):
+ super(VolumeQuotaService, self).__init__(kwargs)
+ self.client = manager.volume_quotas_client
+
+ def delete(self):
+ client = self.client
+ try:
+ client.delete_quota_set(self.tenant_id)
+ except Exception as e:
+ LOG.exception("Delete Volume Quotas exception: %s" % e)
+ pass
+
+ def dry_run(self):
+ quotas = self.client.show_quota_usage(self.tenant_id)
+ self.data['volume_quotas'] = quotas
+
+
+class NovaQuotaService(BaseService):
+ def __init__(self, manager, **kwargs):
+ super(NovaQuotaService, self).__init__(kwargs)
+ self.client = manager.quotas_client
+ self.limits_client = manager.limits_client
+
+ def delete(self):
+ client = self.client
+ try:
+ client.delete_quota_set(self.tenant_id)
+ except Exception as e:
+ LOG.exception("Delete Quotas exception: %s" % e)
+ pass
+
+ def dry_run(self):
+ client = self.limits_client
+ quotas = client.get_absolute_limits()
+ self.data['compute_quotas'] = quotas
+
+
# Begin network service classes
class NetworkService(BaseService):
def __init__(self, manager, **kwargs):
@@ -667,7 +705,7 @@
self.data['pools'] = pools
-class NetworMeteringLabelRuleService(NetworkService):
+class NetworkMeteringLabelRuleService(NetworkService):
def list(self):
client = self.client
@@ -692,7 +730,7 @@
self.data['rules'] = rules
-class NetworMeteringLabelService(NetworkService):
+class NetworkMeteringLabelService(NetworkService):
def list(self):
client = self.client
@@ -1052,6 +1090,7 @@
tenant_services.append(ServerGroupService)
if not IS_NEUTRON:
tenant_services.append(FloatingIpService)
+ tenant_services.append(NovaQuotaService)
if IS_HEAT:
tenant_services.append(StackService)
if IS_NEUTRON:
@@ -1068,8 +1107,8 @@
tenant_services.append(NetworkVipService)
tenant_services.append(NetworkPoolService)
if test.is_extension_enabled('metering', 'network'):
- tenant_services.append(NetworMeteringLabelRuleService)
- tenant_services.append(NetworMeteringLabelService)
+ tenant_services.append(NetworkMeteringLabelRuleService)
+ tenant_services.append(NetworkMeteringLabelService)
tenant_services.append(NetworkRouterService)
tenant_services.append(NetworkFloatingIpService)
tenant_services.append(NetworkPortService)
@@ -1078,6 +1117,7 @@
if IS_CINDER:
tenant_services.append(SnapshotService)
tenant_services.append(VolumeService)
+ tenant_services.append(VolumeQuotaService)
return tenant_services
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 70a8594..f51d9aa 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -94,7 +94,7 @@
versions = map(lambda x: x['id'], body['versions']['values'])
else:
versions = map(lambda x: x['id'], body['versions'])
- return versions
+ return list(versions)
def verify_keystone_api_versions(os, update):
@@ -175,6 +175,7 @@
else:
extensions = map(lambda x: x['alias'], resp)
+ extensions = list(extensions)
if not results.get(service):
results[service] = {}
extensions_opt = get_enabled_extensions(service)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7e0c3b3..50aa261 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -22,7 +22,6 @@
from tempest_lib.common.utils import data_utils
from tempest_lib import exceptions as lib_exc
-from tempest import clients
from tempest.common import fixed_network
from tempest.common.utils.linux import remote_client
from tempest import config
@@ -1341,15 +1340,7 @@
cls.set_network_resources()
super(SwiftScenarioTest, cls).setup_credentials()
operator_role = CONF.object_storage.operator_role
- if not cls.isolated_creds.is_role_available(operator_role):
- skip_msg = ("%s skipped because the configured credential provider"
- " is not able to provide credentials with the %s role "
- "assigned." % (cls.__name__, operator_role))
- raise cls.skipException(skip_msg)
- else:
- cls.os_operator = clients.Manager(
- cls.isolated_creds.get_creds_by_roles(
- [operator_role]))
+ cls.os_operator = cls.get_client_manager(roles=[operator_role])
@classmethod
def setup_clients(cls):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index a73ae1c..8ec10c7 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -440,7 +440,7 @@
@test.idempotent_id('e79f879e-debb-440c-a7e4-efeda05b6848')
@test.services('compute', 'network')
def test_cross_tenant_traffic(self):
- if not self.isolated_creds.is_multi_tenant():
+ if not self.credentials_provider.is_multi_tenant():
raise self.skipException("No secondary tenant defined")
try:
# deploy new tenant
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 60eb1c3..e5613d6 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -41,9 +41,16 @@
self.non_ssh_image_pattern = \
CONF.input_scenario.non_ssh_image_regex
# Setup clients
+ network_resources = {
+ 'network': False,
+ 'router': False,
+ 'subnet': False,
+ 'dhcp': False,
+ }
self.isolated_creds = credentials.get_isolated_credentials(
name='ScenarioImageUtils',
- identity_version=CONF.identity.auth_version)
+ identity_version=CONF.identity.auth_version,
+ network_resources=network_resources)
os = clients.Manager(self.isolated_creds.get_primary_creds())
self.images_client = os.images_client
self.flavors_client = os.flavors_client
@@ -103,9 +110,16 @@
digit=string.digits)
def __init__(self):
+ network_resources = {
+ 'network': False,
+ 'router': False,
+ 'subnet': False,
+ 'dhcp': False,
+ }
self.isolated_creds = credentials.get_isolated_credentials(
name='InputScenarioUtils',
- identity_version=CONF.identity.auth_version)
+ identity_version=CONF.identity.auth_version,
+ network_resources=network_resources)
os = clients.Manager(self.isolated_creds.get_primary_creds())
self.images_client = os.images_client
self.flavors_client = os.flavors_client
diff --git a/tempest/test.py b/tempest/test.py
index aa21c7a..d80e478 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -267,7 +267,7 @@
etype, cls.__name__))
cls.tearDownClass()
try:
- raise etype, value, trace
+ six.reraise(etype, value, trace)
finally:
del trace # to avoid circular refs
@@ -305,7 +305,7 @@
# the first one
if re_raise and etype is not None:
try:
- raise etype, value, trace
+ six.reraise(etype, value, trace)
finally:
del trace # to avoid circular refs
@@ -414,39 +414,80 @@
format=self.log_format,
level=None))
- @classmethod
- def get_client_manager(cls, identity_version=None,
- credential_type='primary'):
- """
- Returns an OpenStack client manager
- """
- force_tenant_isolation = getattr(cls, 'force_tenant_isolation', None)
- identity_version = identity_version or CONF.identity.auth_version
+ @property
+ def credentials_provider(self):
+ return self._get_credentials_provider()
- if (not hasattr(cls, 'isolated_creds') or
- not cls.isolated_creds.name == cls.__name__):
- cls.isolated_creds = credentials.get_isolated_credentials(
+ @classmethod
+ def _get_credentials_provider(cls):
+ """Returns a credentials provider
+
+ If no credential provider exists yet creates one.
+ It uses self.identity_version if defined, or the configuration value
+ """
+ if (not hasattr(cls, '_creds_provider') or not cls._creds_provider or
+ not cls._creds_provider.name == cls.__name__):
+ force_tenant_isolation = getattr(cls, 'force_tenant_isolation',
+ False)
+ identity_version = getattr(cls, 'identity_version', None)
+ identity_version = identity_version or CONF.identity.auth_version
+
+ cls._creds_provider = credentials.get_isolated_credentials(
name=cls.__name__, network_resources=cls.network_resources,
force_tenant_isolation=force_tenant_isolation,
- identity_version=identity_version
- )
+ identity_version=identity_version)
+ return cls._creds_provider
- credentials_method = 'get_%s_creds' % credential_type
- if hasattr(cls.isolated_creds, credentials_method):
- creds = getattr(cls.isolated_creds, credentials_method)()
+ @classmethod
+ def get_client_manager(cls, identity_version=None,
+ credential_type=None, roles=None, force_new=None):
+ """Returns an OpenStack client manager
+
+ Returns an OpenStack client manager based on either credential_type
+ or a list of roles. If neither is specified, it defaults to
+ credential_type 'primary'
+ :param identity_version: string - v2 or v3
+ :param credential_type: string - primary, alt or admin
+ :param roles: list of roles
+
+ :returns the created client manager
+ :raises skipException: if the requested credentials are not available
+ """
+ if all([roles, credential_type]):
+ msg = "Cannot get credentials by type and roles at the same time"
+ raise ValueError(msg)
+ if not any([roles, credential_type]):
+ credential_type = 'primary'
+ cls.identity_version = identity_version
+ cred_provider = cls._get_credentials_provider()
+ if roles:
+ for role in roles:
+ if not cred_provider.is_role_available(role):
+ skip_msg = (
+ "%s skipped because the configured credential provider"
+ " is not able to provide credentials with the %s role "
+ "assigned." % (cls.__name__, role))
+ raise cls.skipException(skip_msg)
+ params = dict(roles=roles)
+ if force_new is not None:
+ params.update(force_new=force_new)
+ creds = cred_provider.get_creds_by_roles(**params)
else:
- raise exceptions.InvalidCredentials(
- "Invalid credentials type %s" % credential_type)
- os = clients.Manager(credentials=creds, service=cls._service)
- return os
+ credentials_method = 'get_%s_creds' % credential_type
+ if hasattr(cred_provider, credentials_method):
+ creds = getattr(cred_provider, credentials_method)()
+ else:
+ raise exceptions.InvalidCredentials(
+ "Invalid credentials type %s" % credential_type)
+ return clients.Manager(credentials=creds, service=cls._service)
@classmethod
def clear_isolated_creds(cls):
"""
Clears isolated creds if set
"""
- if hasattr(cls, 'isolated_creds'):
- cls.isolated_creds.clear_isolated_creds()
+ if hasattr(cls, '_cred_provider'):
+ cls._creds_provider.clear_isolated_creds()
@classmethod
def set_validation_resources(cls, keypair=None, floating_ip=None,
@@ -516,16 +557,16 @@
"""
# Make sure isolated_creds exists and get a network client
networks_client = cls.get_client_manager().networks_client
- isolated_creds = getattr(cls, 'isolated_creds', None)
+ cred_provider = cls._get_credentials_provider()
# In case of nova network, isolated tenants are not able to list the
# network configured in fixed_network_name, even if the can use it
# for their servers, so using an admin network client to validate
# the network name
if (not CONF.service_available.neutron and
credentials.is_admin_available()):
- admin_creds = isolated_creds.get_admin_creds()
+ admin_creds = cred_provider.get_admin_creds()
networks_client = clients.Manager(admin_creds).networks_client
- return fixed_network.get_tenant_network(isolated_creds,
+ return fixed_network.get_tenant_network(cred_provider,
networks_client)
def assertEmpty(self, list, msg=None):
@@ -675,7 +716,7 @@
msg = ("Missing Identity Admin API credentials in"
"configuration.")
raise self.skipException(msg)
- creds = self.isolated_creds.get_admin_creds()
+ creds = self.credentials_provider.get_admin_creds()
os_adm = clients.Manager(credentials=creds)
client = os_adm.negative_client
else:
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index 3a7b436..16f1ac7 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -33,7 +33,7 @@
cmd = ' '.join([cmd, param])
LOG.info("running: '%s'" % cmd)
cmd_str = cmd
- cmd = shlex.split(cmd.encode('utf-8'))
+ cmd = shlex.split(cmd)
result = ''
result_err = ''
try:
diff --git a/tempest/tests/test_glance_http.py b/tempest/tests/test_glance_http.py
index b132f60..7850ee4 100644
--- a/tempest/tests/test_glance_http.py
+++ b/tempest/tests/test_glance_http.py
@@ -137,7 +137,7 @@
resp, body = self.client.raw_request('PUT', '/images', body=req_body)
self.assertEqual(200, resp.status)
self.assertEqual('fake_response_body', body.read())
- httplib.HTTPConnection.send.assert_call_count(req_body.len)
+ httplib.HTTPConnection.send.assert_call_count(req_body.tell())
def test_get_connection_class_for_https(self):
conn_class = self.client.get_connection_class('https')
diff --git a/tempest/tests/test_list_tests.py b/tempest/tests/test_list_tests.py
index 19e4c9c..38d4c5c 100644
--- a/tempest/tests/test_list_tests.py
+++ b/tempest/tests/test_list_tests.py
@@ -14,6 +14,7 @@
import os
import re
+import six
import subprocess
from tempest.tests import base
@@ -32,7 +33,7 @@
self.assertEqual(0, p.returncode,
"test discovery failed, one or more files cause an "
"error on import %s" % ids)
- ids = ids.split('\n')
+ ids = six.text_type(ids).split('\n')
for test_id in ids:
if re.match('(\w+\.){3}\w+', test_id):
if not test_id.startswith('tempest.'):
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 4485972..1ff4dee 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -252,9 +252,9 @@
except exception.BotoServerError as exc:
error_msg = excMatcher.match(exc)
if error_msg is not None:
- raise self.failureException, error_msg
+ raise self.failureException(error_msg)
else:
- raise self.failureException, "BotoServerError not raised"
+ raise self.failureException("BotoServerError not raised")
@classmethod
def resource_cleanup(cls):
diff --git a/tox.ini b/tox.ini
index 88d1302..2d2ed38 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = pep8,py27
+envlist = pep8,py27,py34
minversion = 1.6
skipsdist = True