deb-heat/heat/common/urlfetch.py
Sergey Kraynev ecd8d3999d Replacing variable logger on LOG
Commit https://review.openstack.org/#/c/94255/1 introduces check for
translating log messages. This check uses in pattern name 'LOG', so in
heat code also should be used this name intead of 'logger'. Also same
name is used in other projects.

Change-Id: Iba24c7eb1c13e68a91d090d7bcdbcb40d6e16071
Partial-Bug: #1321283
2014-05-27 15:48:33 -04:00

79 lines
2.8 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Utility for fetching a resource (e.g. a template) from a URL."""
from oslo.config import cfg
import requests
from requests import exceptions
from six.moves import urllib
from heat.common import exception
from heat.openstack.common.gettextutils import _
from heat.openstack.common import log as logging
cfg.CONF.import_opt('max_template_size', 'heat.common.config')
LOG = logging.getLogger(__name__)
class URLFetchError(exception.Error, IOError):
pass
def get(url, allowed_schemes=('http', 'https')):
"""Get the data at the specified URL.
The URL must use the http: or https: schemes.
The file: scheme is also supported if you override
the allowed_schemes argument.
Raise an IOError if getting the data fails.
"""
LOG.info(_('Fetching data from %s') % url)
components = urllib.parse.urlparse(url)
if components.scheme not in allowed_schemes:
raise URLFetchError(_('Invalid URL scheme %s') % components.scheme)
if components.scheme == 'file':
try:
return urllib.request.urlopen(url).read()
except urllib.error.URLError as uex:
raise URLFetchError(_('Failed to retrieve template: %s') % uex)
try:
resp = requests.get(url, stream=True)
resp.raise_for_status()
# We cannot use resp.text here because it would download the
# entire file, and a large enough file would bring down the
# engine. The 'Content-Length' header could be faked, so it's
# necessary to download the content in chunks to until
# max_template_size is reached. The chunk_size we use needs
# to balance CPU-intensive string concatenation with accuracy
# (eg. it's possible to fetch 1000 bytes greater than
# max_template_size with a chunk_size of 1000).
reader = resp.iter_content(chunk_size=1000)
result = ""
for chunk in reader:
result += chunk
if len(result) > cfg.CONF.max_template_size:
raise URLFetchError("Template exceeds maximum allowed size (%s"
" bytes)" % cfg.CONF.max_template_size)
return result
except exceptions.RequestException as ex:
raise URLFetchError(_('Failed to retrieve template: %s') % ex)