Merge "Add option for converting images"
This commit is contained in:
commit
bb3bdaa726
@ -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