--- cloudinit/sources/helpers/openstack.py.orig 2017-07-28 20:28:47.000000000 +0000 +++ cloudinit/sources/helpers/openstack.py 2017-12-21 08:46:06.948988192 +0000 @@ -452,21 +452,22 @@ class MetadataReader(BaseReader): def _path_read(self, path, decode=False): - def should_retry_cb(_request_args, cause): + def should_not_retry_cb(_request_args, cause): try: code = int(cause.code) - if code >= 400: - return False + # FIXME: Would be better to use the required field, but we don't have it here + if code >= 400 and not _request_args['url'][-14:] == 'meta_data.json': + return True except (TypeError, ValueError): # Older versions of requests didn't have a code. pass - return True + return False response = url_helper.readurl(path, retries=self.retries, ssl_details=self.ssl_details, timeout=self.timeout, - exception_cb=should_retry_cb) + exception_cb=should_not_retry_cb) if decode: return response.contents.decode() else: --- cloudinit/url_helper.py.orig 2017-07-28 20:28:47.000000000 +0000 +++ cloudinit/url_helper.py 2017-12-21 08:24:40.320084907 +0000 @@ -260,8 +260,8 @@ def readurl(url, data=None, timeout=None # few seconds break if exception_cb and exception_cb(req_args.copy(), excps[-1]): - # if an exception callback was given it should return None - # a true-ish value means to break and re-raise the exception + # if an exception callback was given it should return False + # to retry and True to interrupt and re-raise the exception break if i + 1 < manual_tries and sec_between > 0: LOG.debug("Please wait %s seconds while we wait to try again",