Use url_for from keystoneclient in swift store
glance doesn't pass ServiceCatalog to glance_store in user context(glance just passes a list of service endpoints). So when swift multi-tenant store is enabled then there is no method url_for for context.service_catalog. We can use ServiceCatalog from keystoneclient for these purposes and convert this list to ServiceCatalog if url_for method is not present. Please also note that keystone.middleware converts X-Service-Catalog to v2 so we can safely initialize and use ServiceCatalogV2 in glance_store. Closes-Bug: #1538482 Change-Id: I3c4c56e91656f09067d28923ed45595395e9880e
This commit is contained in:
parent
30ae6b020c
commit
8677f92877
|
@ -19,6 +19,7 @@ import hashlib
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
from keystoneclient import service_catalog as keystone_sc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
|
@ -871,8 +872,8 @@ class MultiTenantStore(BaseStore):
|
||||||
reason=reason)
|
reason=reason)
|
||||||
self.storage_url = self.conf_endpoint
|
self.storage_url = self.conf_endpoint
|
||||||
if not self.storage_url:
|
if not self.storage_url:
|
||||||
|
sc = {'serviceCatalog': context.service_catalog}
|
||||||
self.storage_url = context.service_catalog.url_for(
|
self.storage_url = keystone_sc.ServiceCatalogV2(sc).url_for(
|
||||||
service_type=self.service_type, region_name=self.region,
|
service_type=self.service_type, region_name=self.region,
|
||||||
endpoint_type=self.endpoint_type)
|
endpoint_type=self.endpoint_type)
|
||||||
|
|
||||||
|
|
|
@ -670,8 +670,21 @@ class SwiftTests(object):
|
||||||
self.config(swift_store_container='container')
|
self.config(swift_store_container='container')
|
||||||
self.config(swift_store_create_container_on_put=True)
|
self.config(swift_store_create_container_on_put=True)
|
||||||
self.config(swift_store_multiple_containers_seed=2)
|
self.config(swift_store_multiple_containers_seed=2)
|
||||||
service_catalog = mock.MagicMock()
|
service_catalog = [
|
||||||
service_catalog.url_for.return_value = 'https://some_endpoint'
|
{
|
||||||
|
'endpoint_links': [],
|
||||||
|
'endpoints': [
|
||||||
|
{
|
||||||
|
'adminURL': 'https://some_admin_endpoint',
|
||||||
|
'region': 'RegionOne',
|
||||||
|
'internalURL': 'https://some_internal_endpoint',
|
||||||
|
'publicURL': 'https://some_endpoint',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'type': 'object-store',
|
||||||
|
'name': 'Object Storage Service',
|
||||||
|
}
|
||||||
|
]
|
||||||
ctxt = mock.MagicMock(
|
ctxt = mock.MagicMock(
|
||||||
user='user', tenant='tenant', auth_token='123',
|
user='user', tenant='tenant', auth_token='123',
|
||||||
service_catalog=service_catalog)
|
service_catalog=service_catalog)
|
||||||
|
@ -1344,8 +1357,22 @@ class TestMultiTenantStoreContext(base.StoreBaseTest):
|
||||||
self.config(**conf)
|
self.config(**conf)
|
||||||
self.store.configure()
|
self.store.configure()
|
||||||
self.register_store_schemes(self.store, 'swift')
|
self.register_store_schemes(self.store, 'swift')
|
||||||
self.service_catalog = mock.MagicMock()
|
service_catalog = [
|
||||||
self.service_catalog.url_for.return_value = "http://127.0.0.1:0"
|
{
|
||||||
|
'endpoint_links': [],
|
||||||
|
'endpoints': [
|
||||||
|
{
|
||||||
|
'region': 'RegionOne',
|
||||||
|
'publicURL': 'http://127.0.0.1:0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'type': 'object-store',
|
||||||
|
'name': 'Object Storage Service',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
self.ctx = mock.MagicMock(
|
||||||
|
service_catalog=service_catalog, user='tenant:user1',
|
||||||
|
tenant='tenant', auth_token='0123')
|
||||||
self.addCleanup(self.conf.reset)
|
self.addCleanup(self.conf.reset)
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
|
@ -1356,12 +1383,8 @@ class TestMultiTenantStoreContext(base.StoreBaseTest):
|
||||||
store.configure()
|
store.configure()
|
||||||
uri = "swift+http://127.0.0.1/glance_123/123"
|
uri = "swift+http://127.0.0.1/glance_123/123"
|
||||||
loc = location.get_location_from_uri(uri, conf=self.conf)
|
loc = location.get_location_from_uri(uri, conf=self.conf)
|
||||||
ctx = mock.MagicMock(
|
|
||||||
service_catalog=self.service_catalog, user='tenant:user1',
|
|
||||||
tenant='tenant', auth_token='0123')
|
|
||||||
|
|
||||||
m.get("http://127.0.0.1/glance_123/123")
|
m.get("http://127.0.0.1/glance_123/123")
|
||||||
store.get(loc, context=ctx)
|
store.get(loc, context=self.ctx)
|
||||||
self.assertEqual(b'0123', m.last_request.headers['X-Auth-Token'])
|
self.assertEqual(b'0123', m.last_request.headers['X-Auth-Token'])
|
||||||
|
|
||||||
@requests_mock.mock()
|
@requests_mock.mock()
|
||||||
|
@ -1377,30 +1400,14 @@ class TestMultiTenantStoreContext(base.StoreBaseTest):
|
||||||
store.configure()
|
store.configure()
|
||||||
content = b'Some data'
|
content = b'Some data'
|
||||||
pseudo_file = six.BytesIO(content)
|
pseudo_file = six.BytesIO(content)
|
||||||
ctx = mock.MagicMock(
|
|
||||||
service_catalog=self.service_catalog, user='tenant:user1',
|
|
||||||
tenant='tenant', auth_token='0123')
|
|
||||||
store.add('123', pseudo_file, len(content),
|
store.add('123', pseudo_file, len(content),
|
||||||
context=ctx)
|
context=self.ctx)
|
||||||
|
|
||||||
self.assertEqual(b'0123',
|
self.assertEqual(b'0123',
|
||||||
head_req.last_request.headers['X-Auth-Token'])
|
head_req.last_request.headers['X-Auth-Token'])
|
||||||
self.assertEqual(b'0123',
|
self.assertEqual(b'0123',
|
||||||
put_req.last_request.headers['X-Auth-Token'])
|
put_req.last_request.headers['X-Auth-Token'])
|
||||||
|
|
||||||
|
|
||||||
class FakeGetEndpoint(object):
|
|
||||||
def __init__(self, response):
|
|
||||||
self.response = response
|
|
||||||
|
|
||||||
def __call__(self, service_catalog, service_type=None,
|
|
||||||
endpoint_region=None, endpoint_type=None):
|
|
||||||
self.service_type = service_type
|
|
||||||
self.endpoint_region = endpoint_region
|
|
||||||
self.endpoint_type = endpoint_type
|
|
||||||
return self.response
|
|
||||||
|
|
||||||
|
|
||||||
class TestCreatingLocations(base.StoreBaseTest):
|
class TestCreatingLocations(base.StoreBaseTest):
|
||||||
_CONF = cfg.CONF
|
_CONF = cfg.CONF
|
||||||
|
|
||||||
|
@ -1414,6 +1421,25 @@ class TestCreatingLocations(base.StoreBaseTest):
|
||||||
moves.reload_module(swift)
|
moves.reload_module(swift)
|
||||||
self.addCleanup(self.conf.reset)
|
self.addCleanup(self.conf.reset)
|
||||||
|
|
||||||
|
service_catalog = [
|
||||||
|
{
|
||||||
|
'endpoint_links': [],
|
||||||
|
'endpoints': [
|
||||||
|
{
|
||||||
|
'adminURL': 'https://some_admin_endpoint',
|
||||||
|
'region': 'RegionOne',
|
||||||
|
'internalURL': 'https://some_internal_endpoint',
|
||||||
|
'publicURL': 'https://some_endpoint',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'type': 'object-store',
|
||||||
|
'name': 'Object Storage Service',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
self.ctxt = mock.MagicMock(user='user', tenant='tenant',
|
||||||
|
auth_token='123',
|
||||||
|
service_catalog=service_catalog)
|
||||||
|
|
||||||
def test_single_tenant_location(self):
|
def test_single_tenant_location(self):
|
||||||
conf = copy.deepcopy(SWIFT_CONF)
|
conf = copy.deepcopy(SWIFT_CONF)
|
||||||
conf['swift_store_container'] = 'container'
|
conf['swift_store_container'] = 'container'
|
||||||
|
@ -1450,85 +1476,48 @@ class TestCreatingLocations(base.StoreBaseTest):
|
||||||
|
|
||||||
def test_multi_tenant_location(self):
|
def test_multi_tenant_location(self):
|
||||||
self.config(swift_store_container='container')
|
self.config(swift_store_container='container')
|
||||||
service_catalog = mock.MagicMock()
|
|
||||||
service_catalog.url_for.return_value = 'https://some_endpoint'
|
|
||||||
ctxt = mock.MagicMock(
|
|
||||||
user='user', tenant='tenant', auth_token='123',
|
|
||||||
service_catalog=service_catalog)
|
|
||||||
store = swift.MultiTenantStore(self.conf)
|
store = swift.MultiTenantStore(self.conf)
|
||||||
store.configure()
|
store.configure()
|
||||||
location = store.create_location('image-id', context=ctxt)
|
location = store.create_location('image-id', context=self.ctxt)
|
||||||
self.assertEqual(location.scheme, 'swift+https')
|
self.assertEqual(location.scheme, 'swift+https')
|
||||||
self.assertEqual(location.swift_url, 'https://some_endpoint')
|
self.assertEqual(location.swift_url, 'https://some_endpoint')
|
||||||
self.assertEqual(location.container, 'container_image-id')
|
self.assertEqual(location.container, 'container_image-id')
|
||||||
self.assertEqual(location.obj, 'image-id')
|
self.assertEqual(location.obj, 'image-id')
|
||||||
self.assertIsNone(location.user)
|
self.assertIsNone(location.user)
|
||||||
self.assertIsNone(location.key)
|
self.assertIsNone(location.key)
|
||||||
service_catalog.url_for.assert_called_once_with(
|
|
||||||
service_type=store.service_type,
|
|
||||||
region_name=store.region,
|
|
||||||
endpoint_type=store.endpoint_type)
|
|
||||||
|
|
||||||
def test_multi_tenant_location_http(self):
|
def test_multi_tenant_location_http(self):
|
||||||
service_catalog = mock.MagicMock()
|
|
||||||
service_catalog.url_for.return_value = 'http://some_endpoint'
|
|
||||||
ctxt = mock.MagicMock(
|
|
||||||
user='user', tenant='tenant', auth_token='123',
|
|
||||||
service_catalog=service_catalog)
|
|
||||||
store = swift.MultiTenantStore(self.conf)
|
store = swift.MultiTenantStore(self.conf)
|
||||||
store.configure()
|
store.configure()
|
||||||
location = store.create_location('image-id', context=ctxt)
|
self.ctxt.service_catalog[0]['endpoints'][0]['publicURL'] = \
|
||||||
self.assertEqual(location.scheme, 'swift+http')
|
'http://some_endpoint'
|
||||||
self.assertEqual(location.swift_url, 'http://some_endpoint')
|
location = store.create_location('image-id', context=self.ctxt)
|
||||||
service_catalog.url_for.assert_called_once_with(
|
self.assertEqual('swift+http', location.scheme)
|
||||||
service_type=store.service_type,
|
self.assertEqual('http://some_endpoint', location.swift_url)
|
||||||
region_name=store.region,
|
|
||||||
endpoint_type=store.endpoint_type)
|
|
||||||
|
|
||||||
def test_multi_tenant_location_with_region(self):
|
def test_multi_tenant_location_with_region(self):
|
||||||
self.config(swift_store_region='WestCarolina')
|
self.config(swift_store_region='WestCarolina')
|
||||||
service_catalog = mock.MagicMock()
|
|
||||||
service_catalog.url_for.return_value = 'https://some_endpoint'
|
|
||||||
ctxt = mock.MagicMock(
|
|
||||||
user='user', tenant='tenant', auth_token='123',
|
|
||||||
service_catalog=service_catalog)
|
|
||||||
store = swift.MultiTenantStore(self.conf)
|
store = swift.MultiTenantStore(self.conf)
|
||||||
store.configure()
|
store.configure()
|
||||||
store._get_endpoint(ctxt)
|
self.ctxt.service_catalog[0]['endpoints'][0]['region'] = 'WestCarolina'
|
||||||
service_catalog.url_for.assert_called_once_with(
|
self.assertEqual('https://some_endpoint',
|
||||||
service_type=store.service_type,
|
store._get_endpoint(self.ctxt))
|
||||||
region_name=store.region,
|
|
||||||
endpoint_type=store.endpoint_type)
|
|
||||||
|
|
||||||
def test_multi_tenant_location_custom_service_type(self):
|
def test_multi_tenant_location_custom_service_type(self):
|
||||||
self.config(swift_store_service_type='toy-store')
|
self.config(swift_store_service_type='toy-store')
|
||||||
service_catalog = mock.MagicMock()
|
self.ctxt.service_catalog[0]['type'] = 'toy-store'
|
||||||
service_catalog.url_for.return_value = 'https://some_endpoint'
|
|
||||||
ctxt = mock.MagicMock(
|
|
||||||
user='user', tenant='tenant', auth_token='123',
|
|
||||||
service_catalog=service_catalog)
|
|
||||||
store = swift.MultiTenantStore(self.conf)
|
store = swift.MultiTenantStore(self.conf)
|
||||||
store.configure()
|
store.configure()
|
||||||
store._get_endpoint(ctxt)
|
store._get_endpoint(self.ctxt)
|
||||||
service_catalog.url_for.assert_called_once_with(
|
self.assertEqual('https://some_endpoint',
|
||||||
service_type=store.service_type,
|
store._get_endpoint(self.ctxt))
|
||||||
region_name=store.region,
|
|
||||||
endpoint_type=store.endpoint_type)
|
|
||||||
|
|
||||||
def test_multi_tenant_location_custom_endpoint_type(self):
|
def test_multi_tenant_location_custom_endpoint_type(self):
|
||||||
self.config(swift_store_endpoint_type='InternalURL')
|
self.config(swift_store_endpoint_type='internalURL')
|
||||||
service_catalog = mock.MagicMock()
|
|
||||||
service_catalog.url_for.return_value = 'https://some_endpoint'
|
|
||||||
ctxt = mock.MagicMock(
|
|
||||||
user='user', tenant='tenant', auth_token='123',
|
|
||||||
service_catalog=service_catalog)
|
|
||||||
store = swift.MultiTenantStore(self.conf)
|
store = swift.MultiTenantStore(self.conf)
|
||||||
store.configure()
|
store.configure()
|
||||||
store._get_endpoint(ctxt)
|
self.assertEqual('https://some_internal_endpoint',
|
||||||
service_catalog.url_for.assert_called_once_with(
|
store._get_endpoint(self.ctxt))
|
||||||
service_type=store.service_type,
|
|
||||||
region_name=store.region,
|
|
||||||
endpoint_type=store.endpoint_type)
|
|
||||||
|
|
||||||
|
|
||||||
class TestChunkReader(base.StoreBaseTest):
|
class TestChunkReader(base.StoreBaseTest):
|
||||||
|
|
|
@ -14,3 +14,4 @@ six>=1.9.0 # MIT
|
||||||
debtcollector>=0.3.0 # Apache-2.0
|
debtcollector>=0.3.0 # Apache-2.0
|
||||||
|
|
||||||
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
|
jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
|
||||||
|
python-keystoneclient>=1.6.0,!=1.8.0,!=2.1.0 # Apache-2.0
|
||||||
|
|
Loading…
Reference in New Issue