Merge "Use the catalog to retrieve glance_api_servers"

This commit is contained in:
Jenkins 2016-03-18 21:41:09 +00:00 committed by Gerrit Code Review
commit 75212a9df6
5 changed files with 60 additions and 22 deletions

View File

@ -54,15 +54,8 @@ global_opts = [
cfg.StrOpt('my_ip',
default=netutils.get_my_ipv4(),
help='IP address of this host'),
cfg.StrOpt('glance_host',
default='$my_ip',
help='Default glance host name or IP'),
cfg.IntOpt('glance_port',
default=9292,
min=1, max=65535,
help='Default glance port'),
cfg.ListOpt('glance_api_servers',
default=['$glance_host:$glance_port'],
default=None,
help='A list of the URLs of glance API servers available to '
'cinder ([http[s]://][hostname|ip]:port). If protocol '
'is not specified it defaults to http.'),

View File

@ -92,7 +92,8 @@ class RequestContext(context.RequestContext):
# Only include required parts of service_catalog
self.service_catalog = [s for s in service_catalog
if s.get('type') in
('identity', 'compute', 'object-store')]
('identity', 'compute', 'object-store',
'image')]
else:
# if list is empty or none
self.service_catalog = []

View File

@ -36,7 +36,7 @@ from six.moves import range
from six.moves import urllib
from cinder import exception
from cinder.i18n import _LE, _LW
from cinder.i18n import _, _LE, _LW
glance_opts = [
@ -45,6 +45,12 @@ glance_opts = [
help='A list of url schemes that can be downloaded directly '
'via the direct_url. Currently supported schemes: '
'[file].'),
cfg.StrOpt('glance_catalog_info',
default='image:glance:publicURL',
help='Info to match when looking for glance in the service '
'catalog. Format is: separated values of the form: '
'<service_type>:<service_name>:<endpoint_type> - '
'Only used if glance_api_servers are not provided.'),
]
glance_core_properties_opts = [
cfg.ListOpt('glance_core_properties',
@ -97,23 +103,44 @@ def _create_glance_client(context, netloc, use_ssl, version=None):
return glanceclient.Client(str(version), endpoint, **params)
def get_api_servers():
def get_api_servers(context):
"""Return Iterable over shuffled api servers.
Shuffle a list of CONF.glance_api_servers and return an iterator
Shuffle a list of glance_api_servers and return an iterator
that will cycle through the list, looping around to the beginning
if necessary.
if necessary. If CONF.glance_api_servers is None then they will
be retrieved from the catalog.
"""
api_servers = []
for api_server in CONF.glance_api_servers:
api_servers_info = []
if CONF.glance_api_servers is None:
info = CONF.glance_catalog_info
try:
service_type, service_name, endpoint_type = info.split(':')
except ValueError:
raise exception.InvalidConfigurationValue(_(
"Failed to parse the configuration option "
"'glance_catalog_info', must be in the form "
"<service_type>:<service_name>:<endpoint_type>"))
for entry in context.service_catalog:
if entry.get('type') == service_type:
api_servers.append(
entry.get('endpoints')[0].get(endpoint_type))
else:
for api_server in CONF.glance_api_servers:
api_servers.append(api_server)
for api_server in api_servers:
if '//' not in api_server:
api_server = 'http://' + api_server
url = urllib.parse.urlparse(api_server)
netloc = url.netloc
use_ssl = (url.scheme == 'https')
api_servers.append((netloc, use_ssl))
random.shuffle(api_servers)
return itertools.cycle(api_servers)
api_servers_info.append((netloc, use_ssl))
random.shuffle(api_servers_info)
return itertools.cycle(api_servers_info)
class GlanceClientWrapper(object):
@ -149,7 +176,7 @@ class GlanceClientWrapper(object):
def _create_onetime_client(self, context, version):
"""Create a client that will be used for one call."""
if self.api_servers is None:
self.api_servers = get_api_servers()
self.api_servers = get_api_servers(context)
self.netloc, self.use_ssl = next(self.api_servers)
return _create_glance_client(context,
self.netloc,

View File

@ -15,6 +15,7 @@
import datetime
import itertools
import glanceclient.exc
import mock
@ -94,8 +95,12 @@ class TestGlanceImageService(test.TestCase):
super(TestGlanceImageService, self).setUp()
client = glance_stubs.StubGlanceClient()
service_catalog = [{u'type': u'image', u'name': u'glance',
u'endpoints': [{
u'publicURL': u'http://example.com:9292'}]}]
self.service = self._create_image_service(client)
self.context = context.RequestContext('fake', 'fake', auth_token=True)
self.context.service_catalog = service_catalog
self.stubs.Set(glance.time, 'sleep', lambda s: None)
def _create_image_service(self, client):
@ -123,6 +128,11 @@ class TestGlanceImageService(test.TestCase):
updated_at=self.NOW_GLANCE_FORMAT,
deleted_at=self.NOW_GLANCE_FORMAT)
def test_get_api_servers(self):
result = glance.get_api_servers(self.context)
expected = (u'example.com:9292', False)
self.assertEqual(expected, next(result))
def test_create_with_instance_id(self):
"""Ensure instance_id is persisted as an image-property."""
fixture = {'name': 'test image',
@ -533,7 +543,10 @@ class TestGlanceImageService(test.TestCase):
@mock.patch('six.moves.builtins.open')
@mock.patch('shutil.copyfileobj')
def test_download_from_direct_file(self, mock_copyfileobj, mock_open):
@mock.patch('cinder.image.glance.get_api_servers',
return_value=itertools.cycle([(False, 'localhost:9292')]))
def test_download_from_direct_file(self, api_servers,
mock_copyfileobj, mock_open):
fixture = self._make_fixture(name='test image',
locations=[{'url': 'file:///tmp/test'}])
image_id = self.service.create(self.context, fixture)['id']
@ -545,7 +558,9 @@ class TestGlanceImageService(test.TestCase):
@mock.patch('six.moves.builtins.open')
@mock.patch('shutil.copyfileobj')
def test_download_from_direct_file_non_file(self,
@mock.patch('cinder.image.glance.get_api_servers',
return_value=itertools.cycle([(False, 'localhost:9292')]))
def test_download_from_direct_file_non_file(self, api_servers,
mock_copyfileobj, mock_open):
fixture = self._make_fixture(name='test image',
direct_url='swift+http://test/image')
@ -734,7 +749,9 @@ class TestGlanceClientVersion(test.TestCase):
self.assertEqual('2', _mockglanceclient.call_args[0][0])
@mock.patch('cinder.image.glance.glanceclient.Client')
def test_call_glance_version_by_arg(self, _mockglanceclient):
@mock.patch('cinder.image.glance.get_api_servers',
return_value=itertools.cycle([(False, 'localhost:9292')]))
def test_call_glance_version_by_arg(self, api_servers, _mockglanceclient):
"""Test glance version set by arg to GlanceClientWrapper"""
glance_wrapper = glance.GlanceClientWrapper()
glance_wrapper.call('fake_context', 'method', version=2)

View File

@ -82,7 +82,7 @@ class ContextTestCase(test.TestCase):
object_catalog = [{u'name': u'swift', u'type': u'object-store'}]
ctxt = context.RequestContext('111', '222',
service_catalog=service_catalog)
self.assertEqual(3, len(ctxt.service_catalog))
self.assertEqual(4, len(ctxt.service_catalog))
return_compute = [v for v in ctxt.service_catalog if
v['type'] == u'compute']
return_object = [v for v in ctxt.service_catalog if