summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tantsur <dtantsur@protonmail.com>2022-10-31 11:19:08 +0100
committerDmitry Tantsur <dtantsur@protonmail.com>2022-11-09 12:26:05 +0000
commit4de58fa80763df74672a8b6d0b73483b1e8ed3e3 (patch)
treeb4c20a7d891f5497f8b27510ef4e9c49a492f65d
parent9a06744458fbab6e44ec4bd8fa9816f65a770d29 (diff)
downloadironic-4de58fa80763df74672a8b6d0b73483b1e8ed3e3.tar.gz
Fix the invalid glance client test
It relied on mocking tenacity.retry, but it's executed on class initialization. Depending on the ordering, it may do nothing or it may replace ImageService.call with a mock. Instead, add a new tenacity helper that loads an option in runtime. As a nice side effect, [glance]num_retries is now mutable. Change-Id: I2e02231d294997e824db77c998ef8d352fa69075 (cherry picked from commit cab51a9fcc022f2e4bb634277dd20e90e2dc78f7)
-rw-r--r--ironic/common/glance_service/image_service.py3
-rw-r--r--ironic/common/utils.py15
-rw-r--r--ironic/conf/glance.py1
-rw-r--r--ironic/tests/unit/common/test_glance_service.py27
4 files changed, 30 insertions, 16 deletions
diff --git a/ironic/common/glance_service/image_service.py b/ironic/common/glance_service/image_service.py
index 0a32eaf0a..1d9d6d4bc 100644
--- a/ironic/common/glance_service/image_service.py
+++ b/ironic/common/glance_service/image_service.py
@@ -33,6 +33,7 @@ from ironic.common.glance_service import service_utils
from ironic.common.i18n import _
from ironic.common import keystone
from ironic.common import swift
+from ironic.common import utils
from ironic.conf import CONF
TempUrlCacheElement = collections.namedtuple('TempUrlCacheElement',
@@ -114,7 +115,7 @@ class GlanceImageService(object):
@tenacity.retry(
retry=tenacity.retry_if_exception_type(
exception.GlanceConnectionFailed),
- stop=tenacity.stop_after_attempt(CONF.glance.num_retries + 1),
+ stop=utils.stop_after_retries('num_retries', group='glance'),
wait=tenacity.wait_fixed(1),
reraise=True
)
diff --git a/ironic/common/utils.py b/ironic/common/utils.py
index e4d83c9b6..9ae88d4d6 100644
--- a/ironic/common/utils.py
+++ b/ironic/common/utils.py
@@ -681,3 +681,18 @@ def is_fips_enabled():
except Exception:
pass
return False
+
+
+def stop_after_retries(option, group=None):
+ """A tenacity retry helper that stops after retries specified in conf."""
+ # NOTE(dtantsur): fetch the option inside of the nested call, otherwise it
+ # cannot be changed in runtime.
+ def should_stop(retry_state):
+ if group:
+ conf = getattr(CONF, group)
+ else:
+ conf = CONF
+ num_retries = getattr(conf, option)
+ return retry_state.attempt_number >= num_retries + 1
+
+ return should_stop
diff --git a/ironic/conf/glance.py b/ironic/conf/glance.py
index a3286b1eb..317f213bc 100644
--- a/ironic/conf/glance.py
+++ b/ironic/conf/glance.py
@@ -114,6 +114,7 @@ opts = [
'will determine how many containers are created.')),
cfg.IntOpt('num_retries',
default=0,
+ mutable=True,
help=_('Number of retries when downloading an image from '
'glance.')),
]
diff --git a/ironic/tests/unit/common/test_glance_service.py b/ironic/tests/unit/common/test_glance_service.py
index 6be0fccd9..a6dd11d3e 100644
--- a/ironic/tests/unit/common/test_glance_service.py
+++ b/ironic/tests/unit/common/test_glance_service.py
@@ -24,7 +24,6 @@ from glanceclient import exc as glance_exc
from keystoneauth1 import loading as ks_loading
from oslo_config import cfg
from oslo_utils import uuidutils
-import tenacity
import testtools
from ironic.common import context
@@ -204,20 +203,18 @@ class TestGlanceImageService(base.TestCase):
image_id = uuidutils.generate_uuid()
writer = NullWriter()
- with mock.patch.object(tenacity, 'retry', autospec=True) as mock_retry:
- # When retries are disabled, we should get an exception
- self.config(num_retries=0, group='glance')
- self.assertRaises(exception.GlanceConnectionFailed,
- stub_service.download, image_id, writer)
-
- # Now lets enable retries. No exception should happen now.
- self.config(num_retries=1, group='glance')
- importlib.reload(image_service)
- stub_service = image_service.GlanceImageService(stub_client,
- stub_context)
- tries = [0]
- stub_service.download(image_id, writer)
- mock_retry.assert_called_once()
+ # When retries are disabled, we should get an exception
+ self.config(num_retries=0, group='glance')
+ self.assertRaises(exception.GlanceConnectionFailed,
+ stub_service.download, image_id, writer)
+
+ # Now lets enable retries. No exception should happen now.
+ self.config(num_retries=1, group='glance')
+ importlib.reload(image_service)
+ stub_service = image_service.GlanceImageService(stub_client,
+ stub_context)
+ tries = [0]
+ stub_service.download(image_id, writer)
def test_download_no_data(self):
self.client.fake_wrapped = None