Merge "Use the catalog to retrieve glance_api_servers"
This commit is contained in:
commit
75212a9df6
|
@ -54,15 +54,8 @@ global_opts = [
|
||||||
cfg.StrOpt('my_ip',
|
cfg.StrOpt('my_ip',
|
||||||
default=netutils.get_my_ipv4(),
|
default=netutils.get_my_ipv4(),
|
||||||
help='IP address of this host'),
|
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',
|
cfg.ListOpt('glance_api_servers',
|
||||||
default=['$glance_host:$glance_port'],
|
default=None,
|
||||||
help='A list of the URLs of glance API servers available to '
|
help='A list of the URLs of glance API servers available to '
|
||||||
'cinder ([http[s]://][hostname|ip]:port). If protocol '
|
'cinder ([http[s]://][hostname|ip]:port). If protocol '
|
||||||
'is not specified it defaults to http.'),
|
'is not specified it defaults to http.'),
|
||||||
|
|
|
@ -92,7 +92,8 @@ class RequestContext(context.RequestContext):
|
||||||
# Only include required parts of service_catalog
|
# Only include required parts of service_catalog
|
||||||
self.service_catalog = [s for s in service_catalog
|
self.service_catalog = [s for s in service_catalog
|
||||||
if s.get('type') in
|
if s.get('type') in
|
||||||
('identity', 'compute', 'object-store')]
|
('identity', 'compute', 'object-store',
|
||||||
|
'image')]
|
||||||
else:
|
else:
|
||||||
# if list is empty or none
|
# if list is empty or none
|
||||||
self.service_catalog = []
|
self.service_catalog = []
|
||||||
|
|
|
@ -36,7 +36,7 @@ from six.moves import range
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _LE, _LW
|
from cinder.i18n import _, _LE, _LW
|
||||||
|
|
||||||
|
|
||||||
glance_opts = [
|
glance_opts = [
|
||||||
|
@ -45,6 +45,12 @@ glance_opts = [
|
||||||
help='A list of url schemes that can be downloaded directly '
|
help='A list of url schemes that can be downloaded directly '
|
||||||
'via the direct_url. Currently supported schemes: '
|
'via the direct_url. Currently supported schemes: '
|
||||||
'[file].'),
|
'[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 = [
|
glance_core_properties_opts = [
|
||||||
cfg.ListOpt('glance_core_properties',
|
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)
|
return glanceclient.Client(str(version), endpoint, **params)
|
||||||
|
|
||||||
|
|
||||||
def get_api_servers():
|
def get_api_servers(context):
|
||||||
"""Return Iterable over shuffled api servers.
|
"""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
|
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 = []
|
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:
|
if '//' not in api_server:
|
||||||
api_server = 'http://' + api_server
|
api_server = 'http://' + api_server
|
||||||
url = urllib.parse.urlparse(api_server)
|
url = urllib.parse.urlparse(api_server)
|
||||||
netloc = url.netloc
|
netloc = url.netloc
|
||||||
use_ssl = (url.scheme == 'https')
|
use_ssl = (url.scheme == 'https')
|
||||||
api_servers.append((netloc, use_ssl))
|
api_servers_info.append((netloc, use_ssl))
|
||||||
random.shuffle(api_servers)
|
|
||||||
return itertools.cycle(api_servers)
|
random.shuffle(api_servers_info)
|
||||||
|
return itertools.cycle(api_servers_info)
|
||||||
|
|
||||||
|
|
||||||
class GlanceClientWrapper(object):
|
class GlanceClientWrapper(object):
|
||||||
|
@ -149,7 +176,7 @@ class GlanceClientWrapper(object):
|
||||||
def _create_onetime_client(self, context, version):
|
def _create_onetime_client(self, context, version):
|
||||||
"""Create a client that will be used for one call."""
|
"""Create a client that will be used for one call."""
|
||||||
if self.api_servers is None:
|
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)
|
self.netloc, self.use_ssl = next(self.api_servers)
|
||||||
return _create_glance_client(context,
|
return _create_glance_client(context,
|
||||||
self.netloc,
|
self.netloc,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import itertools
|
||||||
|
|
||||||
import glanceclient.exc
|
import glanceclient.exc
|
||||||
import mock
|
import mock
|
||||||
|
@ -94,8 +95,12 @@ class TestGlanceImageService(test.TestCase):
|
||||||
super(TestGlanceImageService, self).setUp()
|
super(TestGlanceImageService, self).setUp()
|
||||||
|
|
||||||
client = glance_stubs.StubGlanceClient()
|
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.service = self._create_image_service(client)
|
||||||
self.context = context.RequestContext('fake', 'fake', auth_token=True)
|
self.context = context.RequestContext('fake', 'fake', auth_token=True)
|
||||||
|
self.context.service_catalog = service_catalog
|
||||||
self.stubs.Set(glance.time, 'sleep', lambda s: None)
|
self.stubs.Set(glance.time, 'sleep', lambda s: None)
|
||||||
|
|
||||||
def _create_image_service(self, client):
|
def _create_image_service(self, client):
|
||||||
|
@ -123,6 +128,11 @@ class TestGlanceImageService(test.TestCase):
|
||||||
updated_at=self.NOW_GLANCE_FORMAT,
|
updated_at=self.NOW_GLANCE_FORMAT,
|
||||||
deleted_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):
|
def test_create_with_instance_id(self):
|
||||||
"""Ensure instance_id is persisted as an image-property."""
|
"""Ensure instance_id is persisted as an image-property."""
|
||||||
fixture = {'name': 'test image',
|
fixture = {'name': 'test image',
|
||||||
|
@ -533,7 +543,10 @@ class TestGlanceImageService(test.TestCase):
|
||||||
|
|
||||||
@mock.patch('six.moves.builtins.open')
|
@mock.patch('six.moves.builtins.open')
|
||||||
@mock.patch('shutil.copyfileobj')
|
@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',
|
fixture = self._make_fixture(name='test image',
|
||||||
locations=[{'url': 'file:///tmp/test'}])
|
locations=[{'url': 'file:///tmp/test'}])
|
||||||
image_id = self.service.create(self.context, fixture)['id']
|
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('six.moves.builtins.open')
|
||||||
@mock.patch('shutil.copyfileobj')
|
@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):
|
mock_copyfileobj, mock_open):
|
||||||
fixture = self._make_fixture(name='test image',
|
fixture = self._make_fixture(name='test image',
|
||||||
direct_url='swift+http://test/image')
|
direct_url='swift+http://test/image')
|
||||||
|
@ -734,7 +749,9 @@ class TestGlanceClientVersion(test.TestCase):
|
||||||
self.assertEqual('2', _mockglanceclient.call_args[0][0])
|
self.assertEqual('2', _mockglanceclient.call_args[0][0])
|
||||||
|
|
||||||
@mock.patch('cinder.image.glance.glanceclient.Client')
|
@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"""
|
"""Test glance version set by arg to GlanceClientWrapper"""
|
||||||
glance_wrapper = glance.GlanceClientWrapper()
|
glance_wrapper = glance.GlanceClientWrapper()
|
||||||
glance_wrapper.call('fake_context', 'method', version=2)
|
glance_wrapper.call('fake_context', 'method', version=2)
|
||||||
|
|
|
@ -82,7 +82,7 @@ class ContextTestCase(test.TestCase):
|
||||||
object_catalog = [{u'name': u'swift', u'type': u'object-store'}]
|
object_catalog = [{u'name': u'swift', u'type': u'object-store'}]
|
||||||
ctxt = context.RequestContext('111', '222',
|
ctxt = context.RequestContext('111', '222',
|
||||||
service_catalog=service_catalog)
|
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
|
return_compute = [v for v in ctxt.service_catalog if
|
||||||
v['type'] == u'compute']
|
v['type'] == u'compute']
|
||||||
return_object = [v for v in ctxt.service_catalog if
|
return_object = [v for v in ctxt.service_catalog if
|
||||||
|
|
Loading…
Reference in New Issue