From 0b7febb9a1a9be77d9b794e7901174d8e2e627c0 Mon Sep 17 00:00:00 2001 From: Antonin Ruan Date: Mon, 2 Feb 2026 16:15:47 +0100 Subject: [PATCH] Direct download for object storage PCI-32289 --- glanceclient/v2/images.py | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/glanceclient/v2/images.py b/glanceclient/v2/images.py index d9f3028..ef69d61 100644 --- a/glanceclient/v2/images.py +++ b/glanceclient/v2/images.py @@ -16,6 +16,7 @@ import hashlib import json from oslo_utils import encodeutils +from oslo_log import log as logging from requests import codes import urllib.parse import warlock @@ -24,6 +25,8 @@ from glanceclient.common import utils from glanceclient import exc from glanceclient.v2 import schemas +LOG = logging.getLogger(__name__) + DEFAULT_PAGE_SIZE = 200 SORT_DIR_VALUES = ('asc', 'desc') @@ -216,7 +219,12 @@ class Controller(object): 'This operation is not supported by Glance.') @utils.add_req_id_to_object() - def data(self, image_id, do_checksum=True, allow_md5_fallback=False): + def data(self, + image_id, + do_checksum=True, + allow_md5_fallback=False, + direct_download=False, + ): """Retrieve data of an image. When do_checksum is enabled, validation proceeds as follows: @@ -251,13 +259,31 @@ class Controller(object): meta_hash_value = image_meta.get('os_hash_value', None) meta_hash_algo = image_meta.get('os_hash_algo', None) - url = '/v2/images/%s/file' % image_id - resp, body = self.http_client.get(url) - if resp.status_code == codes.no_content: - return None, resp + file_fallback = False + if direct_download: + url = '/v2/images/%s/direct-download' % image_id + try: + resp, body = self.http_client.get(url) + except exc.HTTPNotImplemented: + LOG.warn("Direct download for %s failed, falling back to " + "download from Glance", image_id) + file_fallback = True + else: + if resp.status_code == codes.no_content: + return None, resp + + if not direct_download or file_fallback: + url = '/v2/images/%s/file' % image_id + resp, body = self.http_client.get(url) + if resp.status_code == codes.no_content: + return None, resp checksum = resp.headers.get('content-md5', None) - content_length = int(resp.headers.get('content-length', 0)) + content_length = 0 + if 'content-length' in resp.headers: + content_length = int(resp.headers['content-length']) + elif 'Content-Length' in resp.headers: + content_length = int(resp.headers['Content-Length']) check_md5sum = do_checksum if do_checksum and meta_hash_value is not None: