Add option for converting images
The review adds an option for converting images to raw format before they are uploaded to glance. In some cases the boot of the image is faster when the image is already in raw format. Story: 2005454 Task: 30506 Change-Id: Ie7226ecaad8feaf0a0c416905cf3e2107d4e8cd3
This commit is contained in:
parent
fa359b84c3
commit
12d4aa0501
@ -312,6 +312,9 @@ def get_arg_parser():
|
||||
parser.add_argument('--flavor-min-disk', default=C.DEFAULT_FLAVOR_DISK,
|
||||
type=int, help="""Specify minimum disk size for new
|
||||
flavours, default is '%s'.""" % C.DEFAULT_FLAVOR_DISK)
|
||||
parser.add_argument('--convert-to-raw', action='store_true', default=False,
|
||||
help="""Convert images to raw format before uploading
|
||||
to glance.""")
|
||||
parser.add_argument('--network-id',
|
||||
help="""Specify which network with external connectivity
|
||||
should be used by the tests.""")
|
||||
@ -528,7 +531,8 @@ def config_tempest(**kwargs):
|
||||
image.set_image_preferences(kwargs.get('image_disk_format',
|
||||
C.DEFAULT_IMAGE_FORMAT),
|
||||
kwargs.get('non_admin', False),
|
||||
no_rng=kwargs.get('no_rng', False))
|
||||
no_rng=kwargs.get('no_rng', False),
|
||||
convert=kwargs.get('convert_to_raw', False))
|
||||
image.create_tempest_images(conf)
|
||||
|
||||
has_neutron = services.is_service("network")
|
||||
@ -573,6 +577,7 @@ def main():
|
||||
config_tempest(
|
||||
append=args.append,
|
||||
cloud_creds=cloud_creds,
|
||||
convert_to_raw=args.convert_to_raw,
|
||||
create=args.create,
|
||||
create_accounts_file=args.create_accounts_file,
|
||||
debug=args.debug,
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
from six.moves import urllib
|
||||
from tempest.lib import exceptions
|
||||
@ -31,15 +32,19 @@ class ImageService(VersionedService):
|
||||
disable_ssl_validation,
|
||||
client)
|
||||
|
||||
def set_image_preferences(self, disk_format, non_admin, no_rng=False):
|
||||
def set_image_preferences(self, disk_format, non_admin, no_rng=False,
|
||||
convert=False):
|
||||
"""Sets image prefferences.
|
||||
|
||||
:type disk_format: string
|
||||
:type non_admin: bool
|
||||
:type no_rng: bool
|
||||
:type convert: bool
|
||||
"""
|
||||
self.disk_format = disk_format
|
||||
self.non_admin = non_admin
|
||||
self.no_rng = no_rng
|
||||
self.convert = convert
|
||||
|
||||
def set_default_tempest_options(self, conf):
|
||||
# When cirros is the image, set validation.image_ssh_user to cirros.
|
||||
@ -90,12 +95,13 @@ class ImageService(VersionedService):
|
||||
img_path = os.path.join(img_dir,
|
||||
os.path.basename(image_path))
|
||||
name = image_path[image_path.rfind('/') + 1:]
|
||||
if self.convert and name[-4:] == ".img":
|
||||
name = name[:-4] + ".raw"
|
||||
if not os.path.exists(img_dir):
|
||||
try:
|
||||
os.makedirs(img_dir)
|
||||
except OSError:
|
||||
raise
|
||||
conf.set('scenario', 'img_file', name)
|
||||
alt_name = name + "_alt"
|
||||
image_id = None
|
||||
if conf.has_option('compute', 'image_ref'):
|
||||
@ -109,7 +115,9 @@ class ImageService(VersionedService):
|
||||
alt_image_id = self.find_or_upload_image(alt_image_id, alt_name,
|
||||
image_source=image_path,
|
||||
image_dest=img_path)
|
||||
|
||||
# get name of the image_id
|
||||
image_id_name = self._find_image(image_id, '')['name']
|
||||
conf.set('scenario', 'img_file', image_id_name)
|
||||
conf.set('compute', 'image_ref', image_id)
|
||||
conf.set('compute', 'image_ref_alt', alt_image_id)
|
||||
|
||||
@ -182,6 +190,9 @@ class ImageService(VersionedService):
|
||||
:type name: string
|
||||
:type path: string
|
||||
"""
|
||||
if self.convert:
|
||||
path = self.convert_image_to_raw(path)
|
||||
|
||||
C.LOG.info("Uploading image '%s' from '%s'",
|
||||
name, os.path.abspath(path))
|
||||
if self.non_admin:
|
||||
@ -225,3 +236,27 @@ class ImageService(VersionedService):
|
||||
data = f.read()
|
||||
with open(destination, "wb") as dest:
|
||||
dest.write(data)
|
||||
|
||||
def convert_image_to_raw(self, path):
|
||||
"""Converts given image to raw format.
|
||||
|
||||
:type path: string
|
||||
:return: path of the converted image
|
||||
:rtype: string
|
||||
"""
|
||||
head, tail = os.path.split(path)
|
||||
name = tail.rsplit('.', 1)[0] + '.raw'
|
||||
raw_path = os.path.join(head, name)
|
||||
# check if converted already
|
||||
if os.path.exists(raw_path):
|
||||
C.LOG.info("Image already converted in '%s'.", raw_path)
|
||||
else:
|
||||
C.LOG.info("Converting image '%s' to '%s'",
|
||||
os.path.abspath(path), os.path.abspath(raw_path))
|
||||
rc = subprocess.call(['qemu-img', 'convert', path, raw_path])
|
||||
if rc != 0:
|
||||
raise Exception("Converting of the image has finished with "
|
||||
"non-zero return code. The return code was "
|
||||
"'%d'", rc)
|
||||
self.disk_format = 'raw'
|
||||
return raw_path
|
||||
|
@ -38,6 +38,7 @@ class TestImageService(BaseServiceTest):
|
||||
disable_ssl_validation=False)
|
||||
self.Service.disk_format = ".format"
|
||||
self.Service.non_admin = False
|
||||
self.Service.convert = False
|
||||
self.Service.client = self.FakeServiceClient()
|
||||
|
||||
self.dir = "/img/"
|
||||
@ -46,11 +47,14 @@ class TestImageService(BaseServiceTest):
|
||||
self.conf.set("image", "image_path", "my_image.qcow2")
|
||||
self.conf.set("image", "http_image", "http_image.qcow2")
|
||||
|
||||
@mock.patch('config_tempest.services.image.ImageService._find_image')
|
||||
@mock.patch('config_tempest.services.image.ImageService'
|
||||
'.find_or_upload_image')
|
||||
@mock.patch('os.makedirs')
|
||||
def _test_create_tempest_images(self, mock_makedirs, mock_find_upload):
|
||||
def _test_create_tempest_images(self, mock_makedirs, mock_find_upload,
|
||||
mock_find_image):
|
||||
mock_find_upload.side_effect = ["id_c", "id_d"]
|
||||
mock_find_image.return_value = {'name': 'my_image.qcow2'}
|
||||
self.Service.create_tempest_images(conf=self.conf)
|
||||
mock_makedirs.assert_called()
|
||||
self.assertEqual(self.conf.get('compute', 'image_ref'), 'id_c')
|
||||
@ -195,3 +199,15 @@ class TestImageService(BaseServiceTest):
|
||||
resp = self.Service._find_image(image_id="001",
|
||||
image_name="cirros")
|
||||
self.assertEqual(resp, expected_resp)
|
||||
|
||||
@mock.patch('subprocess.call')
|
||||
@mock.patch('os.path.exists')
|
||||
def test_convert_image_to_raw(self, mock_exists, mock_subcall):
|
||||
path = '/path/of/my/image.qcow2'
|
||||
raw_path = '/path/of/my/image.raw'
|
||||
mock_exists.return_value = False
|
||||
mock_subcall.return_value = 0
|
||||
self.Service.convert_image_to_raw(path)
|
||||
mock_subcall.assert_called_with(['qemu-img', 'convert',
|
||||
path, raw_path])
|
||||
self.assertEqual(self.Service.disk_format, 'raw')
|
||||
|
@ -401,6 +401,24 @@ image.
|
||||
|
||||
.. _CLI options: ../cli/cli_options.html
|
||||
|
||||
Converting images to .raw format
|
||||
********************************
|
||||
|
||||
By using ``--convert-to-raw`` argument you can make ``python-tempestconf``
|
||||
convert the image given by ``--image`` argument to **.raw** format before
|
||||
uploading it to glance. If Ceph is used as a backend, the boot time of the
|
||||
image will be faster when the image is already in **.raw** format.
|
||||
|
||||
In the following example the ``/my/path/to/myImage.img`` image will be
|
||||
downloaded, then converted to **.raw** format and then uploaded to glance.
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ discover-tempest-config \
|
||||
--os-cloud myCloud \
|
||||
--image /my/path/to/myImage.img \
|
||||
--convert-to-raw
|
||||
|
||||
|
||||
Flavors
|
||||
+++++++
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A new argument for converting images before uploading them to glance
|
||||
is added. If the arugment is used, the images are converted to .raw format.
|
||||
The feature will reduce boot time of the images in case ceph is the
|
||||
backend.
|
Loading…
x
Reference in New Issue
Block a user