This adds a safety check and detection mechanism to the
tools/test_format_inspector.py utility for verifying those features
outside of glance.
Change-Id: I447e7e51315472f8fa6013d4c4852f54c1e0c43d
(cherry picked from commit b27040b87e43ff4acfb6870ef0d13d54e5ca5caa)
(cherry picked from commit b394ef00c3426771092d099cf1d96077bfa4b919)
(cherry picked from commit aa12d39b453068d9ee8367591eb60d4a15cddece)
(cherry picked from commit a1c94b47d0)
115 lines
4.2 KiB
Python
Executable File
115 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright 2020 Red Hat, Inc
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""This is a helper tool to test Glance's stream-based format inspection."""
|
|
|
|
# Example usage:
|
|
#
|
|
# test_format_inspector.py -f qcow2 -v -i ~/cirros-0.5.1-x86_64-disk.img
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
|
|
from oslo_utils import units
|
|
|
|
from glance.common import format_inspector
|
|
from glance.tests.unit.common import test_format_inspector
|
|
|
|
|
|
def main():
|
|
formats = ['raw', 'qcow2', 'vhd', 'vhdx', 'vmdk', 'vdi']
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-d', '--debug', action='store_true')
|
|
parser.add_argument('-f', '--format', default='raw',
|
|
help='Format (%s)' % ','.join(sorted(formats)))
|
|
parser.add_argument('-b', '--block-size', default=65536, type=int,
|
|
help='Block read size')
|
|
parser.add_argument('--context-limit', default=(1 * 1024), type=int,
|
|
help='Maximum memory footprint (KiB)')
|
|
parser.add_argument('-i', '--input', default=None,
|
|
help='Input file. Defaults to stdin')
|
|
parser.add_argument('-v', '--verify', action='store_true',
|
|
help=('Verify our number with qemu-img '
|
|
'(requires --input)'))
|
|
args = parser.parse_args()
|
|
|
|
if args.debug:
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
else:
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
fmt = format_inspector.get_inspector(args.format)(tracing=args.debug)
|
|
|
|
if args.input:
|
|
input_stream = open(args.input, 'rb')
|
|
else:
|
|
input_stream = sys.stdin.buffer
|
|
|
|
stream = format_inspector.InfoWrapper(input_stream, fmt)
|
|
count = 0
|
|
found_size = False
|
|
while True:
|
|
chunk = stream.read(int(args.block_size))
|
|
# This could stream to an output destination or stdin for testing
|
|
# sys.stdout.write(chunk)
|
|
if not chunk:
|
|
break
|
|
count += len(chunk)
|
|
if args.format != 'raw' and not found_size and fmt.virtual_size != 0:
|
|
# Print the point at which we've seen enough of the file to
|
|
# know what the virtual size is. This is almost always less
|
|
# than the raw_size
|
|
print('Determined virtual size at byte %i' % count)
|
|
found_size = True
|
|
|
|
if fmt.format_match:
|
|
print('Source was %s file, virtual size %i MiB (%i bytes)' % (
|
|
fmt, fmt.virtual_size / units.Mi, fmt.virtual_size))
|
|
else:
|
|
print('*** Format inspector did not detect file as %s' % args.format)
|
|
|
|
print('Raw size %i MiB (%i bytes)' % (fmt.actual_size / units.Mi,
|
|
fmt.actual_size))
|
|
print('Required contexts: %s' % str(fmt.context_info))
|
|
mem_total = sum(fmt.context_info.values())
|
|
print('Total memory footprint: %i bytes' % mem_total)
|
|
|
|
# To make sure we're not storing the whole image, complain if the
|
|
# format inspector stored more than context_limit data
|
|
if mem_total > args.context_limit * 1024:
|
|
print('*** ERROR: Memory footprint exceeded!')
|
|
|
|
if args.verify and args.input:
|
|
size = test_format_inspector.get_size_from_qemu_img(args.input)
|
|
if size != fmt.virtual_size:
|
|
print('*** QEMU disagrees with our size of %i: %i' % (
|
|
fmt.virtual_size, size))
|
|
else:
|
|
print('Confirmed size with qemu-img')
|
|
|
|
print('Image safety check: %s' % (
|
|
fmt.safety_check() and 'passed' or 'FAILED'))
|
|
if args.input:
|
|
detected_fmt = format_inspector.detect_file_format(args.input)
|
|
print('Detected inspector for image as: %s' % (
|
|
detected_fmt.__class__.__name__))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|