Merge "Add support for passing image size to Glance API"

This commit is contained in:
Zuul
2025-08-04 13:49:45 +00:00
committed by Gerrit Code Review
5 changed files with 376 additions and 13 deletions
+8 -2
View File
@@ -295,12 +295,17 @@ class Controller(object):
:param image_id: ID of the image to upload data for.
:param image_data: File-like object supplying the data to upload.
:param image_size: Unused - present for backwards compatibility
:param image_size: If present pass it as header
:param u_url: Upload url to upload the data to.
:param backend: Backend store to upload image to.
"""
url = u_url or '/v2/images/%s/file' % image_id
hdrs = {'Content-Type': 'application/octet-stream'}
if image_size is not None:
if not isinstance(image_size, int):
raise TypeError("image_size must be an integer, "
"got %s" % type(image_size).__name__)
hdrs.update({'x-openstack-image-size': '%i' % image_size})
if backend is not None:
hdrs['x-image-meta-store'] = backend
@@ -343,11 +348,12 @@ class Controller(object):
:param image_id: ID of the image to upload data for.
:param image_data: File-like object supplying the data to upload.
:param image_size: Unused - present for backwards compatibility
:param image_size: If present pass it to upload call
"""
url = '/v2/images/%s/stage' % image_id
resp, body = self.upload(image_id,
image_data,
image_size=image_size,
u_url=url)
return body, resp
+37 -6
View File
@@ -49,6 +49,17 @@ def get_image_schema():
return IMAGE_SCHEMA
def get_filesize(args, image_data):
filesize = getattr(args, 'size', None) or utils.get_file_size(image_data)
if getattr(args, 'size', None) and getattr(args, 'file', None):
actual_size = utils.get_file_size(image_data)
if actual_size != args.size:
raise ValueError("Size mismatch: provided size %s does not match "
"the size of the image %s" % (
args.size, actual_size))
return filesize
@utils.schema_args(get_image_schema, omit=['locations', 'os_hidden'])
# NOTE(rosmaita): to make this option more intuitive for end users, we
# do not use the Glance image property name 'os_hidden' here. This means
@@ -66,6 +77,11 @@ def get_image_schema():
help=_('Local file that contains disk image to be uploaded '
'during creation. Alternatively, the image data can be '
'passed to the client via stdin.'))
@utils.arg('--size', metavar='<IMAGE_SIZE>', type=int,
help=_('Size in bytes of image to be uploaded. Default is to get '
'size from provided data object but this is supported in '
'case where size cannot be inferred.'),
default=None)
@utils.arg('--progress', action='store_true', default=False,
help=_('Show upload progress bar.'))
@utils.arg('--store', metavar='<STORE>',
@@ -90,6 +106,11 @@ def do_image_create(gc, args):
backend = args.store
file_name = fields.pop('file', None)
if 'size' in fields:
utils.exit(
"Setting 'size' during image creation is not supported. "
"Please use --size only when uploading data.")
using_stdin = hasattr(sys.stdin, 'isatty') and not sys.stdin.isatty()
if args.store and not (file_name or using_stdin):
utils.exit("--store option should only be provided with --file "
@@ -107,7 +128,6 @@ def do_image_create(gc, args):
if utils.get_data_file(args) is not None:
backend = fields.get('store', None)
args.id = image['id']
args.size = None
do_image_upload(gc, args)
image = gc.images.get(args.id)
finally:
@@ -128,6 +148,11 @@ def do_image_create(gc, args):
help=_('Local file that contains disk image to be uploaded '
'during creation. Alternatively, the image data can be '
'passed to the client via stdin.'))
@utils.arg('--size', metavar='<IMAGE_SIZE>', type=int,
help=_('Size in bytes of image to be uploaded. Default is to get '
'size from provided data object but this is supported in '
'case where size cannot be inferred.'),
default=None)
@utils.arg('--progress', action='store_true', default=False,
help=_('Show upload progress bar.'))
@utils.arg('--import-method', metavar='<METHOD>',
@@ -205,6 +230,11 @@ def do_image_create_via_import(gc, args):
fields[key] = value
file_name = fields.pop('file', None)
if 'size' in fields:
utils.exit(
"Setting 'size' during image creation is not supported. "
"Please use --size only when uploading data.")
using_stdin = hasattr(sys.stdin, 'isatty') and not sys.stdin.isatty()
# special processing for backward compatibility with image-create
@@ -315,7 +345,6 @@ def do_image_create_via_import(gc, args):
args.id = image['id']
if args.import_method:
if utils.get_data_file(args) is not None:
args.size = None
do_image_stage(gc, args)
args.from_create = True
args.stores = stores
@@ -699,13 +728,14 @@ def do_image_upload(gc, args):
_validate_backend(backend, gc)
image_data = utils.get_data_file(args)
filesize = get_filesize(args, image_data)
if args.progress:
filesize = utils.get_file_size(image_data)
if filesize is not None:
# NOTE(kragniz): do not show a progress bar if the size of the
# input is unknown (most likely a piped input)
image_data = progressbar.VerboseFileWrapper(image_data, filesize)
gc.images.upload(args.id, image_data, args.size, backend=backend)
gc.images.upload(args.id, image_data, filesize, backend=backend)
@utils.arg('--file', metavar='<FILE>',
@@ -724,13 +754,14 @@ def do_image_upload(gc, args):
def do_image_stage(gc, args):
"""Upload data for a specific image to staging."""
image_data = utils.get_data_file(args)
filesize = get_filesize(args, image_data)
if args.progress:
filesize = utils.get_file_size(image_data)
if filesize is not None:
# NOTE(kragniz): do not show a progress bar if the size of the
# input is unknown (most likely a piped input)
image_data = progressbar.VerboseFileWrapper(image_data, filesize)
gc.images.stage(args.id, image_data, args.size)
gc.images.stage(args.id, image_data, filesize)
@utils.arg('--import-method', metavar='<METHOD>', default='glance-direct',