Use keystone service catalog for getting auth urls

Co-Authored-By: Andrey Pavlov <apavlov@mirantis.com>

Change-Id: I6c64f4b975d12ccaca564d248f9ccbb02615e19f
Closes-bug: #1371856
This commit is contained in:
Sergey Reshetnyak 2015-03-29 13:11:54 +03:00
parent bfa73fcc5f
commit 4eade5480e
10 changed files with 47 additions and 159 deletions

View File

@ -42,7 +42,6 @@ class Context(context.RequestContext):
roles=None, roles=None,
is_admin=None, is_admin=None,
remote_semaphore=None, remote_semaphore=None,
auth_uri=None,
resource_uuid=None, resource_uuid=None,
current_instance_info=None, current_instance_info=None,
request_id=None, request_id=None,
@ -64,10 +63,6 @@ class Context(context.RequestContext):
self.remote_semaphore = remote_semaphore or semaphore.Semaphore( self.remote_semaphore = remote_semaphore or semaphore.Semaphore(
CONF.cluster_remote_threshold) CONF.cluster_remote_threshold)
self.roles = roles self.roles = roles
if auth_uri:
self.auth_uri = auth_uri
else:
self.auth_uri = _get_auth_uri()
if overwrite or not hasattr(context._request_store, 'context'): if overwrite or not hasattr(context._request_store, 'context'):
self.update_store() self.update_store()
@ -87,7 +82,6 @@ class Context(context.RequestContext):
self.roles, self.roles,
self.is_admin, self.is_admin,
self.remote_semaphore, self.remote_semaphore,
self.auth_uri,
self.resource_uuid, self.resource_uuid,
self.current_instance_info, self.current_instance_info,
self.request_id, self.request_id,
@ -105,7 +99,6 @@ class Context(context.RequestContext):
'project_name': self.tenant_name, 'project_name': self.tenant_name,
'is_admin': self.is_admin, 'is_admin': self.is_admin,
'roles': self.roles, 'roles': self.roles,
'auth_uri': self.auth_uri,
'resource_uuid': self.resource_uuid, 'resource_uuid': self.resource_uuid,
'request_id': self.request_id, 'request_id': self.request_id,
} }
@ -167,28 +160,6 @@ def set_ctx(new_ctx):
setattr(context._request_store, 'context', new_ctx) setattr(context._request_store, 'context', new_ctx)
def _get_auth_uri():
if CONF.keystone_authtoken.auth_uri is not None:
auth_uri = CONF.keystone_authtoken.auth_uri
else:
if CONF.keystone_authtoken.identity_uri is not None:
identity_uri = CONF.keystone_authtoken.identity_uri
else:
host = CONF.keystone_authtoken.auth_host
port = CONF.keystone_authtoken.auth_port
protocol = CONF.keystone_authtoken.auth_protocol
identity_uri = '%s://%s:%s' % (protocol, host, port)
if CONF.use_identity_api_v3 is False:
auth_version = 'v2.0'
else:
auth_version = 'v3'
auth_uri = '%s/%s' % (identity_uri, auth_version)
return auth_uri
def _wrapper(ctx, thread_description, thread_group, func, *args, **kwargs): def _wrapper(ctx, thread_description, thread_group, func, *args, **kwargs):
try: try:
set_ctx(ctx) set_ctx(ctx)

View File

@ -156,5 +156,4 @@ def use_os_admin_auth_token(cluster):
ctx.tenant_id = cluster.tenant_id ctx.tenant_id = cluster.tenant_id
client = keystone.client_for_admin_from_trust(cluster.trust_id) client = keystone.client_for_admin_from_trust(cluster.trust_id)
ctx.auth_token = client.auth_token ctx.auth_token = client.auth_token
ctx.service_catalog = json.dumps( ctx.service_catalog = json.dumps(client.service_catalog.get_data())
client.service_catalog.catalog['catalog'])

View File

@ -18,9 +18,7 @@ from oslo_config import cfg
import six import six
from six.moves.urllib import parse as urlparse from six.moves.urllib import parse as urlparse
from sahara import context
from sahara.utils.openstack import base as clients_base from sahara.utils.openstack import base as clients_base
from sahara.utils.openstack import keystone as k
CONF = cfg.CONF CONF = cfg.CONF
@ -35,8 +33,7 @@ def retrieve_auth_url():
Hadoop Swift library doesn't support keystone v3 api. Hadoop Swift library doesn't support keystone v3 api.
""" """
auth_url = clients_base.url_for(context.current().service_catalog, auth_url = clients_base.retrieve_auth_url()
'identity')
info = urlparse.urlparse(auth_url) info = urlparse.urlparse(auth_url)
if CONF.use_domain_for_proxy_users: if CONF.use_domain_for_proxy_users:
@ -56,22 +53,6 @@ def retrieve_auth_url():
url=url) url=url)
def retrieve_preauth_url():
'''This function returns the storage URL for Swift in the current project.
:returns: The storage URL for the current project's Swift store, or None
if it can't be found.
'''
client = k.client()
catalog = clients_base.execute_with_retries(
client.service_catalog.get_endpoints, 'object-store')
for ep in catalog.get('object-store'):
if ep.get('interface') == 'public':
return ep.get('url')
return None
def inject_swift_url_suffix(url): def inject_swift_url_suffix(url):
if isinstance(url, six.string_types) and url.startswith("swift://"): if isinstance(url, six.string_types) and url.startswith("swift://"):
u = urlparse.urlparse(url) u = urlparse.urlparse(url)

View File

@ -33,7 +33,7 @@ SERVICE_SPECIFIC = ["auth.url", "tenant",
class SwiftIntegrationTestCase(base.SaharaTestCase): class SwiftIntegrationTestCase(base.SaharaTestCase):
@mock.patch('sahara.utils.openstack.base.url_for') @mock.patch('sahara.utils.openstack.base.retrieve_auth_url')
def test_get_swift_configs(self, url_for_mock): def test_get_swift_configs(self, url_for_mock):
url_for_mock.return_value = 'http://localhost:5000/v2.0' url_for_mock.return_value = 'http://localhost:5000/v2.0'
self.setup_context(tenant_name='test_tenant') self.setup_context(tenant_name='test_tenant')

View File

@ -25,7 +25,7 @@ class SwiftUtilsTest(testbase.SaharaTestCase):
super(SwiftUtilsTest, self).setUp() super(SwiftUtilsTest, self).setUp()
self.override_config('use_identity_api_v3', True) self.override_config('use_identity_api_v3', True)
@mock.patch('sahara.utils.openstack.base.url_for') @mock.patch('sahara.utils.openstack.base.retrieve_auth_url')
def test_retrieve_auth_url(self, url_for_mock): def test_retrieve_auth_url(self, url_for_mock):
correct = "https://127.0.0.1:8080/v2.0/" correct = "https://127.0.0.1:8080/v2.0/"
@ -41,7 +41,7 @@ class SwiftUtilsTest(testbase.SaharaTestCase):
_assert("https://127.0.0.1:8080/v42/") _assert("https://127.0.0.1:8080/v42/")
_assert("https://127.0.0.1:8080/foo") _assert("https://127.0.0.1:8080/foo")
@mock.patch('sahara.utils.openstack.base.url_for') @mock.patch('sahara.utils.openstack.base.retrieve_auth_url')
def test_retrieve_auth_url_without_port(self, url_for_mock): def test_retrieve_auth_url_without_port(self, url_for_mock):
correct = "https://127.0.0.1/v2.0/" correct = "https://127.0.0.1/v2.0/"

View File

@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import functools
import random import random
import fixtures import fixtures
@ -23,7 +22,6 @@ import testtools
from sahara import context from sahara import context
from sahara import exceptions as ex from sahara import exceptions as ex
from sahara.tests.unit import base as test_base
rnd = random.Random() rnd = random.Random()
@ -137,31 +135,3 @@ class ContextTest(testtools.TestCase):
class TestException(Exception): class TestException(Exception):
pass pass
class GetAuthURITest(test_base.SaharaTestCase):
def setUp(self):
super(GetAuthURITest, self).setUp()
self.override_auth_config = functools.partial(
self.override_config, group='keystone_authtoken')
def test_get_auth_url_from_auth_uri_param(self):
self.override_auth_config('auth_uri', 'http://pony:5000/v2.0')
self.assertEqual('http://pony:5000/v2.0', context._get_auth_uri())
def test_get_auth_uri_from_identity_uri(self):
self.override_auth_config('identity_uri', 'http://spam:35357')
self.assertEqual('http://spam:35357/v3', context._get_auth_uri())
self.override_config('use_identity_api_v3', False)
self.assertEqual('http://spam:35357/v2.0', context._get_auth_uri())
def test_get_auth_uri_from_auth_params(self):
self.override_auth_config('auth_host', 'eggs')
self.override_auth_config('auth_port', 12345)
self.override_auth_config('auth_protocol', 'http')
self.assertEqual('http://eggs:12345/v3', context._get_auth_uri())
self.override_config('use_identity_api_v3', False)
self.assertEqual('http://eggs:12345/v2.0', context._get_auth_uri())

View File

@ -58,10 +58,10 @@ class AuthUrlTest(testbase.SaharaTestCase):
def test_retrieve_auth_url_api_v3(self): def test_retrieve_auth_url_api_v3(self):
self.override_config('use_identity_api_v3', True) self.override_config('use_identity_api_v3', True)
correct = "https://127.0.0.1:8080/v3/" correct = "https://127.0.0.1:8080/v3"
def _assert(uri): def _assert(uri):
self.setup_context(auth_uri=uri) self.override_config('auth_uri', uri, 'keystone_authtoken')
self.assertEqual(correct, base.retrieve_auth_url()) self.assertEqual(correct, base.retrieve_auth_url())
_assert("%s/" % correct) _assert("%s/" % correct)
@ -74,12 +74,14 @@ class AuthUrlTest(testbase.SaharaTestCase):
_assert("https://127.0.0.1:8080/v42") _assert("https://127.0.0.1:8080/v42")
_assert("https://127.0.0.1:8080/v42/") _assert("https://127.0.0.1:8080/v42/")
def test_retrieve_auth_url_api_v3_without_port(self): @mock.patch("sahara.utils.openstack.base.url_for")
def test_retrieve_auth_url_api_v3_without_port(self, mock_url_for):
self.override_config('use_identity_api_v3', True) self.override_config('use_identity_api_v3', True)
correct = "https://127.0.0.1/v3/" self.setup_context(service_catalog=True)
correct = "https://127.0.0.1/v3"
def _assert(uri): def _assert(uri):
self.setup_context(auth_uri=uri) mock_url_for.return_value = uri
self.assertEqual(correct, base.retrieve_auth_url()) self.assertEqual(correct, base.retrieve_auth_url())
_assert("%s/" % correct) _assert("%s/" % correct)
@ -94,10 +96,10 @@ class AuthUrlTest(testbase.SaharaTestCase):
def test_retrieve_auth_url_api_v20(self): def test_retrieve_auth_url_api_v20(self):
self.override_config('use_identity_api_v3', False) self.override_config('use_identity_api_v3', False)
correct = "https://127.0.0.1:8080/v2.0/" correct = "https://127.0.0.1:8080/v2.0"
def _assert(uri): def _assert(uri):
self.setup_context(auth_uri=uri) self.override_config('auth_uri', uri, 'keystone_authtoken')
self.assertEqual(correct, base.retrieve_auth_url()) self.assertEqual(correct, base.retrieve_auth_url())
_assert("%s/" % correct) _assert("%s/" % correct)
@ -110,12 +112,14 @@ class AuthUrlTest(testbase.SaharaTestCase):
_assert("https://127.0.0.1:8080/v42") _assert("https://127.0.0.1:8080/v42")
_assert("https://127.0.0.1:8080/v42/") _assert("https://127.0.0.1:8080/v42/")
def test_retrieve_auth_url_api_v20_without_port(self): @mock.patch("sahara.utils.openstack.base.url_for")
def test_retrieve_auth_url_api_v20_without_port(self, mock_url_for):
self.override_config('use_identity_api_v3', False) self.override_config('use_identity_api_v3', False)
correct = "https://127.0.0.1/v2.0/" self.setup_context(service_catalog=True)
correct = "https://127.0.0.1/v2.0"
def _assert(uri): def _assert(uri):
self.setup_context(auth_uri=uri) mock_url_for.return_value = uri
self.assertEqual(correct, base.retrieve_auth_url()) self.assertEqual(correct, base.retrieve_auth_url())
_assert("%s/" % correct) _assert("%s/" % correct)

View File

@ -29,6 +29,8 @@ class FakeImage(object):
class TestImages(base.SaharaTestCase): class TestImages(base.SaharaTestCase):
@mock.patch('sahara.utils.openstack.base.url_for', return_value='') @mock.patch('sahara.utils.openstack.base.url_for', return_value='')
def test_list_registered_images(self, url_for_mock): def test_list_registered_images(self, url_for_mock):
self.override_config('auth_uri', 'https://127.0.0.1:8080/v3/',
'keystone_authtoken')
some_images = [ some_images = [
FakeImage('foo', ['bar', 'baz'], 'test'), FakeImage('foo', ['bar', 'baz'], 'test'),
FakeImage('baz', [], 'test'), FakeImage('baz', [], 'test'),

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from keystoneclient import exceptions as keystone_ex
from keystoneclient import service_catalog as keystone_service_catalog
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils as json from oslo_serialization import jsonutils as json
@ -20,7 +22,6 @@ from six.moves.urllib import parse as urlparse
from sahara import context from sahara import context
from sahara import exceptions as ex from sahara import exceptions as ex
from sahara.i18n import _
from sahara.i18n import _LE from sahara.i18n import _LE
from sahara.i18n import _LW from sahara.i18n import _LW
@ -47,74 +48,32 @@ CONF.register_group(retries)
CONF.register_opts(opts, group=retries) CONF.register_opts(opts, group=retries)
def url_for(service_catalog, service_type, admin=False, endpoint_type=None): def url_for(service_catalog=None, service_type='identity',
if not endpoint_type: endpoint_type='publicURL'):
endpoint_type = 'publicURL' if not service_catalog:
if admin: service_catalog = context.current().service_catalog
endpoint_type = 'adminURL' try:
return keystone_service_catalog.ServiceCatalogV2(
service = _get_service_from_catalog(service_catalog, service_type) {'serviceCatalog': json.loads(service_catalog)}).url_for(
service_type=service_type, endpoint_type=endpoint_type,
if service: region_name=CONF.os_region_name)
endpoints = service['endpoints'] except keystone_ex.EndpointNotFound:
if CONF.os_region_name: ctx = context.current()
endpoints = [e for e in endpoints return keystone_service_catalog.ServiceCatalogV3(
if e['region'] == CONF.os_region_name] ctx.auth_token,
try: {'catalog': json.loads(service_catalog)}).url_for(
return _get_endpoint_url(endpoints, endpoint_type) service_type=service_type, endpoint_type=endpoint_type,
except Exception: region_name=CONF.os_region_name)
raise ex.SystemError(
_("Endpoint with type %(type)s is not found for service "
"%(service)s")
% {'type': endpoint_type,
'service': service_type})
else:
raise ex.SystemError(
_('Service "%s" not found in service catalog') % service_type)
def _get_service_from_catalog(catalog, service_type):
if catalog:
catalog = json.loads(catalog)
for service in catalog:
if service['type'] == service_type:
return service
return None
def _get_endpoint_url(endpoints, endpoint_type):
if 'interface' in endpoints[0]:
endpoint_type = endpoint_type[0:-3]
for endpoint in endpoints:
if endpoint['interface'] == endpoint_type:
return endpoint['url']
return _get_case_insensitive(endpoints[0], endpoint_type)
def _get_case_insensitive(dictionary, key):
for k, v in dictionary.items():
if str(k).lower() == str(key).lower():
return v
# this will raise an exception as usual if key was not found
return dictionary[key]
def retrieve_auth_url(): def retrieve_auth_url():
info = urlparse.urlparse(context.current().auth_uri)
version = 'v3' if CONF.use_identity_api_v3 else 'v2.0' version = 'v3' if CONF.use_identity_api_v3 else 'v2.0'
ctx = context.current()
if info.port: if ctx.service_catalog:
return "%s://%s:%s/%s/" % (info.scheme, info = urlparse.urlparse(url_for(ctx.service_catalog, 'identity'))
info.hostname,
info.port,
version)
else: else:
return "%s://%s/%s/" % (info.scheme, info = urlparse.urlparse(CONF.keystone_authtoken.auth_uri)
info.hostname, return "%s://%s/%s" % (info[:2] + (version,))
version)
def execute_with_retries(method, *args, **kwargs): def execute_with_retries(method, *args, **kwargs):

View File

@ -18,6 +18,7 @@ import swiftclient
from sahara.swift import swift_helper as sh from sahara.swift import swift_helper as sh
from sahara.swift import utils as su from sahara.swift import utils as su
from sahara.utils.openstack import base
from sahara.utils.openstack import keystone as k from sahara.utils.openstack import keystone as k
opts = [ opts = [
@ -76,7 +77,8 @@ def client_from_token(token):
return swiftclient.Connection(auth_version='2.0', return swiftclient.Connection(auth_version='2.0',
cacert=CONF.swift.ca_file, cacert=CONF.swift.ca_file,
insecure=CONF.swift.api_insecure, insecure=CONF.swift.api_insecure,
preauthurl=su.retrieve_preauth_url(), preauthurl=base.url_for(
service_type="object-store"),
preauthtoken=token, preauthtoken=token,
retries=CONF.retries.retries_number, retries=CONF.retries.retries_number,
retry_on_ratelimit=True, retry_on_ratelimit=True,