Fix retry mechanism for generator results
Both v1 and v2 of the glance client return python generators in some
cases (rather than fully fleshed out lists) which thwarts our retry
mechanism. Convert generator results to a list, so that any potential
exceptions get raised earlier rather than later, allowing for retries.
Change-Id: Ibc84f1596d4eaabdef0a48f6cf4da2d1323843a8
Closes-Bug: #1557584
(cherry picked from commit ae6d868e2f
)
This commit is contained in:
parent
61b4dcc18f
commit
3771c37bac
|
@ -18,6 +18,7 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
import inspect
|
||||
import itertools
|
||||
import random
|
||||
import sys
|
||||
|
@ -246,7 +247,12 @@ class GlanceClientWrapper(object):
|
|||
client = self.client or self._create_onetime_client(context,
|
||||
version)
|
||||
try:
|
||||
return getattr(client.images, method)(*args, **kwargs)
|
||||
result = getattr(client.images, method)(*args, **kwargs)
|
||||
if inspect.isgenerator(result):
|
||||
# Convert generator results to a list, so that we can
|
||||
# catch any potential exceptions now and retry the call.
|
||||
return list(result)
|
||||
return result
|
||||
except retry_excs as e:
|
||||
if attempt < num_attempts:
|
||||
extra = "retrying"
|
||||
|
|
|
@ -381,6 +381,39 @@ class TestGlanceClientWrapper(test.NoDBTestCase):
|
|||
self.assertEqual(str(client.api_server), "https://host2:9293")
|
||||
sleep_mock.assert_called_once_with(1)
|
||||
|
||||
@mock.patch('random.shuffle')
|
||||
@mock.patch('time.sleep')
|
||||
@mock.patch('nova.image.glance._glanceclient_from_endpoint')
|
||||
def test_retry_works_with_generators(self, create_client_mock,
|
||||
sleep_mock, shuffle_mock):
|
||||
def some_generator(exception):
|
||||
if exception:
|
||||
raise glanceclient.exc.CommunicationError('Boom!')
|
||||
yield 'something'
|
||||
|
||||
api_servers = [
|
||||
'https://host2:9292',
|
||||
'https://host2:9293',
|
||||
'http://host3:9294'
|
||||
]
|
||||
client_mock = mock.MagicMock()
|
||||
images_mock = mock.MagicMock()
|
||||
images_mock.list.side_effect = [
|
||||
some_generator(exception=True),
|
||||
some_generator(exception=False),
|
||||
]
|
||||
type(client_mock).images = mock.PropertyMock(return_value=images_mock)
|
||||
create_client_mock.return_value = client_mock
|
||||
|
||||
self.flags(num_retries=1, group='glance')
|
||||
self.flags(api_servers=api_servers, group='glance')
|
||||
|
||||
ctx = context.RequestContext('fake', 'fake')
|
||||
client = glance.GlanceClientWrapper()
|
||||
client.call(ctx, 1, 'list', 'meow')
|
||||
sleep_mock.assert_called_once_with(1)
|
||||
self.assertEqual(str(client.api_server), 'https://host2:9293')
|
||||
|
||||
@mock.patch('oslo_service.sslutils.is_enabled')
|
||||
@mock.patch('glanceclient.Client')
|
||||
def test_create_glance_client_with_ssl(self, client_mock,
|
||||
|
|
Loading…
Reference in New Issue