summaryrefslogtreecommitdiff
path: root/ironic/common/images.py
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-07-14 01:28:00 +0000
committerGerrit Code Review <review@openstack.org>2022-07-14 01:28:00 +0000
commit5d2283137c6d083668eec1c7bed7696a06dbafe6 (patch)
tree1f4562d2bf4bc53e056c684af8f931e6e8d02740 /ironic/common/images.py
parent442aeca6520aebd69b0fc1fb13a1d1aea4843058 (diff)
parente78f123ff8e3a4fcd5e3e596b526eb5eb39a34a9 (diff)
downloadironic-5d2283137c6d083668eec1c7bed7696a06dbafe6.tar.gz
Merge "Make anaconda non-image deploys sane"
Diffstat (limited to 'ironic/common/images.py')
-rw-r--r--ironic/common/images.py75
1 files changed, 74 insertions, 1 deletions
diff --git a/ironic/common/images.py b/ironic/common/images.py
index bffff8807..2b52b789b 100644
--- a/ironic/common/images.py
+++ b/ironic/common/images.py
@@ -580,7 +580,8 @@ def is_whole_disk_image(ctx, instance_info):
:param instance_info: a node's instance info dict
:returns: True for whole disk images and False for partition images
- and None on no image_source or Error.
+ and None on no image_source, the source being a path, or upon an
+ Error.
"""
image_source = instance_info.get('image_source')
if not image_source:
@@ -606,6 +607,11 @@ def is_whole_disk_image(ctx, instance_info):
and not iproperties.get('ramdisk_id'))
else:
# Non glance image ref
+ if is_source_a_path(ctx, instance_info.get('image_source')):
+ # Nothing is returned if not valid or there was an error.
+ # A third possibility is it is not a disk image, which would
+ # still be None.
+ return
if (not instance_info.get('kernel')
and not instance_info.get('ramdisk')):
is_whole_disk_image = True
@@ -613,6 +619,73 @@ def is_whole_disk_image(ctx, instance_info):
return is_whole_disk_image
+def is_source_a_path(ctx, image_source):
+ """Determine if the image source is a path.
+
+ This method determines if a supplied URL is a path.
+
+ :param ctx: an admin/process context.
+ :param image_source: The supplied image source, expected to be a
+ URL, which can be used to attempt to determine
+ if the source is a path.
+ :returns: True if the image_source appears to be a path as opposed
+ to an image to be downloaded. If the image source is not
+ a path, False is returned. If any error is detected,
+ None is returned.
+ """
+ if not image_source:
+ return
+ image_service = service.get_image_service(image_source,
+ context=ctx)
+ try:
+ res = image_service.validate_href(image_source)
+ if 'headers' in dir(res):
+ # response/result is from the HTTP check path.
+ headers = res.headers
+ else:
+ # We have no headers.
+ headers = {}
+ except exception.ImageRefIsARedirect as e:
+ # Our exception handling formats this for us in this
+ # case. \o/
+ LOG.debug(str(e))
+ # Servers redirect to a proper folder ending in a slash if
+ # not supplied originally.
+ if e.redirect_url and e.redirect_url.endswith('/'):
+ return True
+ except Exception:
+ # NOTE(TheJulia): I don't really like this pattern, *but*
+ # the wholedisk image support is similar.
+ return
+ # When issuing a head request, folders have no length
+ # A list can be generated by the server.. This is a solid
+ # hint.
+ if 'Content-Length' in headers:
+ LOG.debug('Evaluated %(url)s to determine if it is a URL to a path '
+ 'or a file. A Content-Length header was returned '
+ 'suggesting file.',
+ {'url': image_source})
+ # NOTE(TheJulia): Files on a webserver have a length which is returned
+ # when headres are queried.
+ return False
+ if ('Content-Type' in headers
+ and str(headers['Content-Type']).startswith('text')
+ and 'Content-Length' not in headers):
+ LOG.debug('Evaluated %(url)s to determine if it is a URL to a path '
+ 'or a file. A Content-Type header was returned with a text '
+ 'content, which suggests a file list was returned.',
+ {'url': image_source})
+ return True
+ # NOTE(TheJulia): Files should have been caught almost exclusively
+ # before with the Content-Length check.
+ if image_source.endswith('/'):
+ # If all else fails, looks like a URL, and the server didn't give
+ # us any hints.
+ return True
+ # We were unable to determine if this was a folder or a file.
+ return False
+
+
def _extract_iso(extract_iso, extract_dir):
# NOTE(rpittau): we could probably just extract the files we need
# if we find them. Also we probably need to detect the correct iso