Merge "Iterate over glance API servers"

This commit is contained in:
Jenkins 2014-10-31 14:59:56 +00:00 committed by Gerrit Code Review
commit 0272fff8fd
4 changed files with 87 additions and 16 deletions

View File

@ -825,7 +825,7 @@
# A list of the glance api servers available to ironic. Prefix
# with https:// for SSL-based glance API servers. Format is
# [hostname|IP]:port. (string value)
# [hostname|IP]:port. (list value)
#glance_api_servers=<None>
# Allow to perform insecure SSL (https) requests to glance.

View File

@ -15,7 +15,9 @@
# under the License.
import copy
import itertools
import logging
import random
from oslo.config import cfg
from oslo.serialization import jsonutils
@ -29,6 +31,9 @@ from ironic.common import exception
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
_GLANCE_API_SERVER = None
""" iterator that cycles (indefinitely) over glance API servers. """
def generate_glance_url():
"""Generate the URL to glance."""
@ -105,24 +110,54 @@ def _remove_read_only(image_meta):
return output
def _get_api_server():
"""Get the Glance API server information."""
api_server = (CONF.glance.glance_api_servers or
CONF.glance.glance_host + ':' + str(CONF.glance.glance_port))
def _get_api_server_iterator():
"""Return iterator over shuffled API servers.
Shuffle a list of CONF.glance.glance_api_servers and return an iterator
that will cycle through the list, looping around to the beginning if
necessary.
If CONF.glance.glance_api_servers isn't set, we fall back to using this
as the server: CONF.glance.glance_host:CONF.glance.glance_port.
:returns: iterator that cycles (indefinitely) over shuffled glance API
servers. The iterator returns tuples of (host, port, use_ssl).
"""
api_servers = []
configured_servers = (CONF.glance.glance_api_servers or
['%s:%s' % (CONF.glance.glance_host,
CONF.glance.glance_port)])
for api_server in configured_servers:
if '//' not in api_server:
api_server = CONF.glance.glance_protocol + '://' + api_server
api_server = '%s://%s' % (CONF.glance.glance_protocol, api_server)
url = urlparse.urlparse(api_server)
port = url.port or 80
host = url.netloc.split(':', 1)[0]
use_ssl = (url.scheme == 'https')
return host, port, use_ssl
api_servers.append((host, port, use_ssl))
random.shuffle(api_servers)
return itertools.cycle(api_servers)
def _get_api_server():
"""Return a Glance API server.
:returns: for an API server, the tuple (host-or-IP, port, use_ssl), where
use_ssl is True to use the 'https' scheme, and False to use 'http'.
"""
global _GLANCE_API_SERVER
if not _GLANCE_API_SERVER:
_GLANCE_API_SERVER = _get_api_server_iterator()
return _GLANCE_API_SERVER.next()
def parse_image_ref(image_href):
"""Parse an image href into composite parts.
:param image_href: href of an image
:returns: a tuple of the form (image_id, host, port)
:returns: a tuple of the form (image_id, host, port, use_ssl)
:raises ValueError
"""

View File

@ -30,7 +30,7 @@ glance_opts = [
default='http',
help='Default protocol to use when connecting to glance. '
'Set to https for SSL.'),
cfg.StrOpt('glance_api_servers',
cfg.ListOpt('glance_api_servers',
help='A list of the glance api servers available to ironic. '
'Prefix with https:// for SSL-based glance API servers. '
'Format is [hostname|IP]:port.'),

View File

@ -752,3 +752,39 @@ class TestServiceUtils(base.TestCase):
generated_url = service_utils.generate_image_url(image_href)
self.assertEqual('https://123.123.123.123:1234/images/image_uuid',
generated_url)
class TestGlanceAPIServers(base.TestCase):
def setUp(self):
super(TestGlanceAPIServers, self).setUp()
service_utils._GLANCE_API_SERVER = None
def test__get_api_servers_default(self):
host, port, use_ssl = service_utils._get_api_server()
self.assertEqual(CONF.glance.glance_host, host)
self.assertEqual(CONF.glance.glance_port, port)
self.assertEqual(CONF.glance.glance_protocol == 'https', use_ssl)
def test__get_api_servers_one(self):
CONF.set_override('glance_api_servers', ['https://10.0.0.1:9293'],
'glance')
s1 = service_utils._get_api_server()
s2 = service_utils._get_api_server()
self.assertEqual(('10.0.0.1', 9293, True), s1)
# Only one server, should always get the same one
self.assertEqual(s1, s2)
def test__get_api_servers_two(self):
CONF.set_override('glance_api_servers',
['http://10.0.0.1:9293', 'http://10.0.0.2:9294'],
'glance')
s1 = service_utils._get_api_server()
s2 = service_utils._get_api_server()
s3 = service_utils._get_api_server()
self.assertNotEqual(s1, s2)
# 2 servers, so cycles to the first again
self.assertEqual(s1, s3)