Catalog driver generates v3 catalog from v2 catalog

The default get_v3_catalog method in the catalog driver would just
raise NotImplemented. This method is given a default implementation
that generates the v3 catalog by translating the v2 catalog.

With this change, the templated and kvs catalog backends can
generate a v3 catalog.

Closes-Bug: #1313458
Change-Id: I1646c7dcab90f2e0e9e370f48f7ee3643bd2fe3d
This commit is contained in:
Brant Knudson 2014-02-02 15:17:13 -06:00
parent 6f12495ed1
commit 8b9580456a
6 changed files with 75 additions and 20 deletions

View File

@ -15,7 +15,6 @@
from keystone import catalog
from keystone.common import kvs
from keystone import exception
class Catalog(kvs.Base, catalog.Driver):
@ -138,6 +137,3 @@ class Catalog(kvs.Base, catalog.Driver):
def _create_catalog(self, user_id, tenant_id, data):
self.db.set('catalog-%s-%s' % (tenant_id, user_id), data)
return data
def get_v3_catalog(self, user_id, tenant_id, metadata=None):
raise exception.NotImplemented()

View File

@ -19,7 +19,6 @@ import six
from keystone.catalog.backends import kvs
from keystone.catalog import core
from keystone import config
from keystone import exception
from keystone.openstack.common.gettextutils import _
from keystone.openstack.common import log
from keystone.openstack.common import versionutils
@ -121,9 +120,6 @@ class Catalog(kvs.Catalog):
return o
def get_v3_catalog(self, user_id, tenant_id, metadata=None):
raise exception.NotImplemented()
@versionutils.deprecated(
versionutils.deprecated.ICEHOUSE,

View File

@ -334,10 +334,11 @@ class Driver(object):
"""
raise exception.NotImplemented()
@abc.abstractmethod
def get_v3_catalog(self, user_id, tenant_id, metadata=None):
"""Retrieve and format the current V3 service catalog.
The default implementation builds the V3 catalog from the V2 catalog.
Example::
[
@ -363,4 +364,35 @@ class Driver(object):
:raises: keystone.exception.NotFound
"""
raise exception.NotImplemented()
v2_catalog = self.get_catalog(user_id, tenant_id, metadata=metadata)
v3_catalog = []
for region_name, region in six.iteritems(v2_catalog):
for service_type, service in six.iteritems(region):
service_v3 = {
'type': service_type,
'endpoints': []
}
for attr, value in six.iteritems(service):
# Attributes that end in URL are interfaces. In the V2
# catalog, these are internalURL, publicURL, and adminURL.
# For example, <region_name>.publicURL=<URL> in the V2
# catalog becomes the V3 interface for the service:
# { 'interface': 'public', 'url': '<URL>', 'region':
# 'region: '<region_name>' }
if attr.endswith('URL'):
v3_interface = attr[:-len('URL')]
service_v3['endpoints'].append({
'interface': v3_interface,
'region': region_name,
'url': value,
})
continue
# Other attributes are copied to the service.
service_v3[attr] = value
v3_catalog.append(service_v3)
return v3_catalog

View File

@ -224,8 +224,11 @@ class KvsCatalog(tests.TestCase, test_backend.CatalogTests):
self.assertRaises(exception.NotFound, f)
def test_get_v3_catalog_endpoint_disabled(self):
# There's no need to have disabled endpoints in the kvs catalog. Those
# endpoints should just be removed from the store. This just tests
# what happens currently when the super impl is called.
f = super(KvsCatalog, self).test_get_v3_catalog_endpoint_disabled
self.assertRaises(exception.NotImplemented, f)
self.assertRaises(exception.NotFound, f)
class KvsTokenCacheInvalidation(tests.TestCase,

View File

@ -13,6 +13,7 @@
# under the License.
import os
import uuid
from keystone import exception
from keystone import tests
@ -73,6 +74,37 @@ class TestTemplatedCatalog(tests.TestCase, test_backend.CatalogTests):
self.skipTest("Templated backend doesn't have disabled endpoints")
def test_get_v3_catalog_endpoint_disabled(self):
f = (super(TestTemplatedCatalog, self).
test_get_v3_catalog_endpoint_disabled)
self.assertRaises(exception.NotImplemented, f)
self.skipTest("Templated backend doesn't have disabled endpoints")
def test_get_v3_catalog(self):
user_id = uuid.uuid4().hex
project_id = uuid.uuid4().hex
catalog_ref = self.catalog_api.get_v3_catalog(user_id, project_id)
exp_catalog = [
{'endpoints': [
{'interface': 'admin',
'region': 'RegionOne',
'url': 'http://localhost:8774/v1.1/%s' % project_id},
{'interface': 'public',
'region': 'RegionOne',
'url': 'http://localhost:8774/v1.1/%s' % project_id},
{'interface': 'internal',
'region': 'RegionOne',
'url': 'http://localhost:8774/v1.1/%s' % project_id}],
'type': 'compute',
'name': "'Compute Service'",
'id': '2'},
{'endpoints': [
{'interface': 'admin',
'region': 'RegionOne',
'url': 'http://localhost:35357/v2.0'},
{'interface': 'public',
'region': 'RegionOne',
'url': 'http://localhost:5000/v2.0'},
{'interface': 'internal',
'region': 'RegionOne',
'url': 'http://localhost:35357/v2.0'}],
'type': 'identity',
'name': "'Identity Service'",
'id': '1'}]
self.assertEqual(exp_catalog, catalog_ref)

View File

@ -305,12 +305,8 @@ class V3TokenDataHelper(object):
if CONF.trust.enabled and trust:
user_id = trust['trustor_user_id']
if project_id or domain_id:
try:
service_catalog = self.catalog_api.get_v3_catalog(
user_id, project_id)
except exception.NotImplemented:
service_catalog = {}
# TODO(gyee): v3 service catalog is not quite completed yet
service_catalog = self.catalog_api.get_v3_catalog(
user_id, project_id)
# TODO(ayoung): Enforce Endpoints for trust
token_data['catalog'] = service_catalog