diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample index d12da448ae..8429cd0b9b 100644 --- a/etc/tempest.conf.sample +++ b/etc/tempest.conf.sample @@ -10,18 +10,8 @@ catalog_type = identity # Ignore SSL certificate validation failures? Use when in testing # environments that have self-signed SSL certs. disable_ssl_certificate_validation = False -# Set to True if your test environment's Keystone authentication service should -# be accessed over HTTPS -use_ssl = False -# This is the main host address of the authentication service API -host = 127.0.0.1 -# Port that the authentication service API is running on -port = 5000 -# Version of the authentication service API (a string) -api_version = v2.0 -# Path to the authentication service tokens resource (do not modify unless you -# have a custom authentication API and are not using Keystone) -path = tokens +# URL for where to find the OpenStack Identity API endpoint (Keystone) +uri = http://127.0.0.1:5000/v2.0/ # Should typically be left as keystone unless you have a non-Keystone # authentication API service strategy = keystone diff --git a/stress/tools/nova_destroy_all.py b/stress/tools/nova_destroy_all.py index 21cac11f8c..0070e72e93 100755 --- a/stress/tools/nova_destroy_all.py +++ b/stress/tools/nova_destroy_all.py @@ -24,7 +24,7 @@ identity = tempest.config.TempestConfig().identity compute = tempest.config.TempestConfig().compute nt = client.Client(compute.username, compute.password, - compute.tenant_name, identity.auth_url) + compute.tenant_name, identity.uri) flavor_list = nt.flavors.list() server_list = nt.servers.list() diff --git a/stress/tools/nova_status.py b/stress/tools/nova_status.py index d413d7a37e..f9bc707bb1 100755 --- a/stress/tools/nova_status.py +++ b/stress/tools/nova_status.py @@ -23,10 +23,10 @@ import tempest.config identity = tempest.config.TempestConfig().identity compute = tempest.config.TempestConfig().compute print compute.username, compute.password,\ - compute.tenant_name, identity.auth_url + compute.tenant_name, identity.uri nt = client.Client(compute.username, compute.password, - compute.tenant_name, identity.auth_url) + compute.tenant_name, identity.uri) flavor_list = nt.flavors.list() server_list = nt.servers.list() diff --git a/tempest/clients.py b/tempest/clients.py index 0bb17522e8..98ae3f68c6 100644 --- a/tempest/clients.py +++ b/tempest/clients.py @@ -164,7 +164,7 @@ class Manager(object): "tenant_name: %(tenant_name)s") % locals() raise exceptions.InvalidConfiguration(msg) - self.auth_url = self.config.identity.auth_url + self.auth_url = self.config.identity.uri if self.config.identity.strategy == 'keystone': client_args = (self.config, self.username, self.password, diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py index 7beef3fcd2..4213b10f60 100644 --- a/tempest/common/rest_client.py +++ b/tempest/common/rest_client.py @@ -116,6 +116,10 @@ class RestClient(object): Provides authentication via Keystone """ + # Normalize URI to ensure /tokens is in it. + if 'tokens' not in auth_url: + auth_url = auth_url.rstrip('/') + '/tokens' + creds = { 'auth': { 'passwordCredentials': { diff --git a/tempest/config.py b/tempest/config.py index 45e8bc4f79..70b1c79fd7 100644 --- a/tempest/config.py +++ b/tempest/config.py @@ -34,21 +34,25 @@ IdentityGroup = [ cfg.BoolOpt('disable_ssl_certificate_validation', default=False, help="Set to True if using self-signed SSL certificates."), + cfg.StrOpt('uri', + default=None, + help="Full URI of the OpenStack Identity API (Keystone)"), cfg.StrOpt('host', default="127.0.0.1", - help="Host IP for making Identity API requests."), + help="(DEPRECATED, use uri) Host IP for making Identity " + "API requests."), cfg.IntOpt('port', default=8773, - help="Port for the Identity service."), + help="(DEPRECATED, use uri) Port for the Identity service."), cfg.StrOpt('api_version', default="v1.1", - help="Version of the Identity API"), + help="(DEPRECATED, use uri) Version of the Identity API"), cfg.StrOpt('path', default='/', - help="Path of API request"), + help="(IGNORED) Path of API request"), cfg.BoolOpt('use_ssl', default=False, - help="Specifies if we are using https."), + help="(DEPRECATED, use uri) Specifies if we are using https."), cfg.StrOpt('strategy', default='keystone', help="Which auth method does the environment use? " @@ -64,16 +68,15 @@ def register_identity_opts(conf): for opt in IdentityGroup: conf.register_opt(opt, group='identity') + # Fall back to piecemeal identity URI for legacy support authurl = data_utils.build_url(conf.identity.host, str(conf.identity.port), conf.identity.api_version, - conf.identity.path, + path='', # Ignore path... use_ssl=conf.identity.use_ssl) - auth_url = cfg.StrOpt('auth_url', - default=authurl, - help="The Identity URL (derived)") - conf.register_opt(auth_url, group="identity") + if not conf.identity.uri: + conf.identity.uri = authurl identity_admin_group = cfg.OptGroup(name='identity-admin', diff --git a/tempest/manager.py b/tempest/manager.py index cfe8a5cb90..8e7cbd17b5 100644 --- a/tempest/manager.py +++ b/tempest/manager.py @@ -126,8 +126,7 @@ class DefaultClientManager(Manager): "tenant_name: %(tenant_name)s") % locals() raise exceptions.InvalidConfiguration(msg) - # Novaclient adds a /tokens/ part to the auth URL automatically - auth_url = self.config.identity.auth_url.rstrip('tokens') + auth_url = self.config.identity.uri dscv = self.config.identity.disable_ssl_certificate_validation client_args = (username, password, tenant_name, auth_url) @@ -166,7 +165,7 @@ class DefaultClientManager(Manager): "tenant_name: %(tenant_name)s") % locals() raise exceptions.InvalidConfiguration(msg) - auth_url = self.config.identity.auth_url.rstrip('tokens') + auth_url = self.config.identity.uri dscv = self.config.identity.disable_ssl_certificate_validation return keystoneclient.v2_0.client.Client(username=username, @@ -192,7 +191,7 @@ class DefaultClientManager(Manager): "tenant_name: %(tenant_name)s") % locals() raise exceptions.InvalidConfiguration(msg) - auth_url = self.config.identity.auth_url.rstrip('tokens') + auth_url = self.config.identity.uri dscv = self.config.identity.disable_ssl_certificate_validation return quantumclient.v2_0.client.Client(username=username, @@ -233,7 +232,11 @@ class ComputeFuzzClientManager(FuzzClientManager): "tenant_name: %(tenant_name)s") % locals() raise exceptions.InvalidConfiguration(msg) - auth_url = self.config.identity.auth_url + auth_url = self.config.identity.uri + + # Ensure /tokens is in the URL for Keystone... + if 'tokens' not in auth_url: + auth_url = auth_url.rstrip('/') + '/tokens' if self.config.identity.strategy == 'keystone': client_args = (self.config, username, password, auth_url, diff --git a/tempest/services/boto/__init__.py b/tempest/services/boto/__init__.py index 1365435a11..83bf1f9968 100644 --- a/tempest/services/boto/__init__.py +++ b/tempest/services/boto/__init__.py @@ -38,10 +38,6 @@ class BotoClientBase(object): self.connection_timeout = str(config.boto.http_socket_timeout) self.num_retries = str(config.boto.num_retries) self.build_timeout = config.boto.build_timeout - # We do not need the "path": "/token" part - if auth_url: - auth_url = re.sub("(.*)" + re.escape(config.identity.path) + "$", - "\\1", auth_url) self.ks_cred = {"username": username, "password": password, "auth_url": auth_url, diff --git a/tempest/services/identity/json/admin_client.py b/tempest/services/identity/json/admin_client.py index a0da4cafdb..7b1cb4bb05 100644 --- a/tempest/services/identity/json/admin_client.py +++ b/tempest/services/identity/json/admin_client.py @@ -206,7 +206,14 @@ class AdminClientJSON(RestClient): class TokenClientJSON(RestClient): def __init__(self, config): - self.auth_url = config.identity.auth_url + auth_url = config.identity.uri + + # TODO(jaypipes) Why is this all repeated code in here? + # Normalize URI to ensure /tokens is in it. + if 'tokens' not in auth_url: + auth_url = auth_url.rstrip('/') + '/tokens' + + self.auth_url = auth_url self.config = config def auth(self, user, password, tenant): diff --git a/tempest/services/identity/xml/admin_client.py b/tempest/services/identity/xml/admin_client.py index 46a1255a9b..1c71d87de2 100644 --- a/tempest/services/identity/xml/admin_client.py +++ b/tempest/services/identity/xml/admin_client.py @@ -242,7 +242,14 @@ class AdminClientXML(RestClientXML): class TokenClientXML(RestClientXML): def __init__(self, config): - self.auth_url = config.identity.auth_url + auth_url = config.identity.uri + + # TODO(jaypipes) Why is this all repeated code in here? + # Normalize URI to ensure /tokens is in it. + if 'tokens' not in auth_url: + auth_url = auth_url.rstrip('/') + '/tokens' + + self.auth_url = auth_url self.config = config def auth(self, user, password, tenant): diff --git a/tempest/services/image/service.py b/tempest/services/image/service.py index 3ffdd1030f..cf4ff4dff8 100644 --- a/tempest/services/image/service.py +++ b/tempest/services/image/service.py @@ -42,8 +42,7 @@ class Service(BaseService): import keystoneclient.v2_0.client dscv = self.config.identity.disable_ssl_certificate_validation - - auth_url = self.config.identity.auth_url.rstrip('tokens') + auth_url = self.config.identity.uri keystone = keystoneclient.v2_0.client.Client( username=config.images.username, password=config.images.password, diff --git a/tempest/tests/compute/admin/test_quotas.py b/tempest/tests/compute/admin/test_quotas.py index 452de80a82..eaf245a50a 100644 --- a/tempest/tests/compute/admin/test_quotas.py +++ b/tempest/tests/compute/admin/test_quotas.py @@ -30,7 +30,7 @@ class QuotasTest(BaseComputeTest): adm_user = cls.config.compute_admin.username adm_pass = cls.config.compute_admin.password adm_tenant = cls.config.compute_admin.tenant_name - auth_url = cls.config.identity.auth_url + auth_url = cls.config.identity.uri cls.adm_client = adm_quotas.AdminQuotasClient(cls.config, adm_user, adm_pass, auth_url, diff --git a/tempest/tests/compute/base.py b/tempest/tests/compute/base.py index 8044d01f29..c44a2f1d4d 100644 --- a/tempest/tests/compute/base.py +++ b/tempest/tests/compute/base.py @@ -89,7 +89,7 @@ class BaseCompTest(unittest.TestCase): cls.config, cls.config.identity_admin.username, cls.config.identity_admin.password, - cls.config.identity.auth_url + cls.config.identity.uri ) @classmethod diff --git a/tempest/tests/volume/admin/base.py b/tempest/tests/volume/admin/base.py index 81c7c78508..d35efbc105 100644 --- a/tempest/tests/volume/admin/base.py +++ b/tempest/tests/volume/admin/base.py @@ -35,7 +35,7 @@ class BaseVolumeAdminTest(BaseVolumeTest): cls.adm_user = cls.config.compute_admin.username cls.adm_pass = cls.config.compute_admin.password cls.adm_tenant = cls.config.compute_admin.tenant_name - cls.auth_url = cls.config.identity.auth_url + cls.auth_url = cls.config.identity.uri if not cls.adm_user and cls.adm_pass and cls.adm_tenant: msg = ("Missing Volume Admin API credentials " diff --git a/tempest/tests/volume/admin/test_volume_types.py b/tempest/tests/volume/admin/test_volume_types.py index 65c975a139..a907a79b1c 100644 --- a/tempest/tests/volume/admin/test_volume_types.py +++ b/tempest/tests/volume/admin/test_volume_types.py @@ -28,7 +28,7 @@ class VolumeTypesTest(BaseVolumeTest): adm_user = cls.config.compute_admin.username adm_pass = cls.config.compute_admin.password adm_tenant = cls.config.compute_admin.tenant_name - auth_url = cls.config.identity.auth_url + auth_url = cls.config.identity.uri cls.client = volume_types_client.VolumeTypesClientJSON(cls.config, adm_user, diff --git a/tempest/tests/volume/admin/test_volume_types_extra_specs.py b/tempest/tests/volume/admin/test_volume_types_extra_specs.py index 9734c42075..c5a1fa9a2e 100644 --- a/tempest/tests/volume/admin/test_volume_types_extra_specs.py +++ b/tempest/tests/volume/admin/test_volume_types_extra_specs.py @@ -29,7 +29,7 @@ class VolumeTypesExtraSpecsTest(BaseVolumeTest): adm_user = cls.config.compute_admin.username adm_pass = cls.config.compute_admin.password adm_tenant = cls.config.compute_admin.tenant_name - auth_url = cls.config.identity.auth_url + auth_url = cls.config.identity.uri cls.client = volume_types_client.VolumeTypesClientJSON(cls.config, adm_user, diff --git a/tools/tempest_coverage.py b/tools/tempest_coverage.py index 73dcfbcac7..6e7ac04b88 100755 --- a/tools/tempest_coverage.py +++ b/tools/tempest_coverage.py @@ -139,7 +139,7 @@ def parse_opts(argv): def main(argv): CLI = parse_opts(argv) client_args = (CONF, CONF.compute_admin.username, - CONF.compute_admin.password, CONF.identity.auth_url, + CONF.compute_admin.password, CONF.identity.uri, CONF.compute_admin.tenant_name) coverage_client = CoverageClientJSON(*client_args)