Skip to content

Commit 80b2748

Browse files
committed
ovirt-img: command testing
Add the required testing infrastructure to test ovirt-img command with a local setup. Engine configuration needs to be set in a configuration file, and then the tests will read this configuration and run normally through tox. The test are run through a new tox environment, namely client (as it tests commands contained in the client folder): tox -e client It will read the configuration in the default location run the tests in the test/client folder. Configuration location can be set through an env variable: CLIENT_TEST_CONF=/path/to/test.conf tox -e client Currently, it only tests upload and download commands, with different formats and comparing resulting images. Example: $ CLIENT_TEST_CONF=~/.config/ovirt-img.conf tox -e client -- --log-cli-level=debug collected 2 items test/client/upload_download_test.py::test_upload_download[raw] Formatting '/var/tmp/imageio-tests/test_upload_download_raw_0/image.raw', fmt=raw size=10737418240 12:26:37,374 INFO (MainThread) [test] Upload raw image to SD nfs-01 [ 100% ] 10.00 GiB, 19.08 s, 536.59 MiB/s | upload completed 12:26:56,595 INFO (MainThread) [test] Download image d27c0e2f-35d1-4106-96e6-215022e022bf [ 100% ] 10.00 GiB, 2.47 s, 4.05 GiB/s | download completed 12:26:59,202 INFO (MainThread) [test] Comparing images 12:26:59,539 INFO (MainThread) [test] Upload raw image to SD iscsi-01 [ 100% ] 10.00 GiB, 24.73 s, 414.15 MiB/s | upload completed 12:27:24,405 INFO (MainThread) [test] Download image a3b48896-33bc-4f62-b3af-159b56686a29 [ 100% ] 10.00 GiB, 4.73 s, 2.11 GiB/s | download completed 12:27:29,277 INFO (MainThread) [test] Comparing images PASSED test/client/upload_download_test.py::test_upload_download[qcow2] Formatting '/var/tmp/imageio-tests/test_upload_download_qcow2_0/image.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10737418240 lazy_refcounts=off refcount_bits=16 12:27:30,103 INFO (MainThread) [test] Upload qcow2 image to SD nfs-01 [ 100% ] 10.00 GiB, 11.92 s, 858.81 MiB/s | upload completed 12:27:42,175 INFO (MainThread) [test] Download image 9cb8da7a-6169-4020-8233-9f20aeeef56e [ 100% ] 10.00 GiB, 2.44 s, 4.09 GiB/s | download completed 12:27:44,765 INFO (MainThread) [test] Comparing images 12:27:45,956 INFO (MainThread) [test] Upload qcow2 image to SD iscsi-01 [ 100% ] 10.00 GiB, 29.13 s, 351.49 MiB/s | upload completed 12:28:15,236 INFO (MainThread) [test] Download image ae41f54d-0345-40ac-bf40-197430c671f5 [ 100% ] 10.00 GiB, 2.92 s, 3.43 GiB/s | download completed 12:28:18,290 INFO (MainThread) [test] Comparing images PASSED Fixes: oVirt#124 Signed-off-by: Albert Esteve <aesteve@redhat.com>
1 parent 2f1d3a1 commit 80b2748

File tree

4 files changed

+165
-3
lines changed

4 files changed

+165
-3
lines changed

test/client/client_tests.conf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Example configuration for client tests.
2+
# Adapt these settings to your local engine setup and then run:
3+
# tox -e client
4+
# This configuration can be copied to a different location and used as
5+
# CLIENT_TEST_CONF=/path/to/test.conf tox -e client
6+
7+
# Common parameters must be all kept, and are used by all tests
8+
common:
9+
engine_url: https://engine.com
10+
username: admin@internal
11+
password: password
12+
cafile: /path/to/cert.pem
13+
14+
tests:
15+
# Image upload and download test. Different formats are tested.
16+
# Image and disk contents are compared.
17+
upload-download:
18+
# Set local storage domain names to test.
19+
# At least one block and one file storage domain shall be tested.
20+
storage-domains:
21+
- nfs1
22+
- scsi1

test/client/conftest.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# ovirt-imageio
2+
# Copyright (C) 2022 Red Hat, Inc.
3+
#
4+
# This program is free software; you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation; either version 2 of the License, or
7+
# (at your option) any later version.
8+
9+
import logging
10+
import os
11+
import yaml
12+
13+
import pytest
14+
15+
16+
log = logging.getLogger("test")
17+
18+
19+
@pytest.fixture
20+
def config(tmpdir):
21+
with open(os.environ['CLIENT_TEST_CONF'], encoding='utf-8') as fstream:
22+
try:
23+
conf = yaml.safe_load(fstream)
24+
except yaml.YAMLError as exc:
25+
log.error("Invalid YAML format: %s", exc)
26+
raise
27+
28+
conf_file = os.path.join(tmpdir, 'ovirt-img.conf')
29+
os.environ['XDG_CONFIG_HOME'] = str(tmpdir)
30+
with open(conf_file, "w+", encoding="utf-8") as fstream:
31+
fstream.write("[test]\n")
32+
for k, v in conf["common"].items():
33+
fstream.write(f"{k} = {v}\n")
34+
35+
yield conf

test/client/upload_download_test.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# ovirt-imageio
2+
# Copyright (C) 2022 Red Hat, Inc.
3+
#
4+
# This program is free software; you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation; either version 2 of the License, or
7+
# (at your option) any later version.
8+
9+
import contextlib
10+
import logging
11+
import os
12+
import uuid
13+
import subprocess
14+
import sys
15+
16+
import pytest
17+
import ovirtsdk4 as sdk
18+
19+
from ovirt_imageio._internal import qemu_img
20+
21+
22+
log = logging.getLogger("test")
23+
24+
25+
class ClientError(Exception):
26+
pass
27+
28+
29+
def run_upload_disk(storage_domain, image, disk_id=None, log_level=None):
30+
# Make sure it runs with the same tox environment executable
31+
cmd = [sys.executable, './ovirt-img', 'upload-disk', '-c', 'test']
32+
cmd.extend(['-s', storage_domain])
33+
if log_level:
34+
cmd.extend(['--log-level', log_level])
35+
if disk_id:
36+
cmd.extend(['--disk-id', disk_id])
37+
cmd.append(image)
38+
try:
39+
subprocess.run(cmd, check=True)
40+
except subprocess.CalledProcessError as exc:
41+
raise ClientError(f'Client Error: {exc}') from exc
42+
43+
44+
def run_download_disk(disk_id, image, log_level=None):
45+
# Make sure it runs with the same tox environment executable
46+
cmd = [sys.executable, './ovirt-img', 'download-disk', '-c', 'test']
47+
if log_level:
48+
cmd.extend(['--log-level', log_level])
49+
cmd.extend([disk_id, image])
50+
try:
51+
subprocess.run(cmd, check=True)
52+
except subprocess.CalledProcessError as exc:
53+
raise ClientError(f'Client Error: {exc}') from exc
54+
55+
56+
def remove_disk(conf, sd_name, disk_id):
57+
connection = sdk.Connection(
58+
url=f'{conf["engine_url"]}/ovirt-engine/api',
59+
username=conf["username"],
60+
password=conf["password"],
61+
ca_file=conf["cafile"]
62+
)
63+
with contextlib.closing(connection):
64+
sd_service = connection.system_service().storage_domains_service()
65+
found_sd = sd_service.list(search=f'name={sd_name}')
66+
if not found_sd:
67+
raise RuntimeError(f"Couldn't find storage domain {sd_name}")
68+
69+
sd = found_sd[0]
70+
sd_service = sd_service.storage_domain_service(sd.id)
71+
sd_service.disks_service().disk_service(disk_id).remove()
72+
73+
74+
@pytest.mark.parametrize("fmt", ["raw", "qcow2"])
75+
def test_upload_download(config, tmpdir, fmt):
76+
image = os.path.join(tmpdir, f'image.{fmt}')
77+
qemu_img.create(image, fmt, size='10g')
78+
test_config = config["tests"]["upload-download"]
79+
for sd_name in test_config.get("storage-domains", []):
80+
disk_id = str(uuid.uuid4())
81+
try:
82+
log.info("Upload %s image to SD %s", fmt, sd_name)
83+
run_upload_disk(sd_name, image, disk_id)
84+
down_img = os.path.join(tmpdir, f'downloaded.{fmt}')
85+
log.info("Download image %s", disk_id)
86+
run_download_disk(disk_id, down_img)
87+
log.info("Comparing images")
88+
qemu_img.compare(image, down_img)
89+
except ClientError as exc:
90+
log.error("%s", exc)
91+
# Skip disk cleanup if client failed
92+
return
93+
finally:
94+
remove_disk(config["common"], sd_name, disk_id)

tox.ini

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# and then run "tox" from this directory.
55

66
[tox]
7-
envlist = flake8,test-{py36,py38,py39,py310},bench-{py36,py38,py39,py310}
7+
envlist = flake8,test-{py36,py38,py39,py310},bench-{py36,py38,py39,py310},client
88
skip_missing_interpreters = True
99
whitelist_externals =
1010
ip
@@ -25,8 +25,19 @@ commands_pre =
2525
/usr/bin/python3 setup.py build_ext --build-lib .
2626
python -c 'from test import testutil; print("ipv6 supported: %s" % testutil.ipv6_enabled())'
2727
commands =
28-
test: pytest -m 'not benchmark' --cov=ovirt_imageio --durations=10 {posargs}
29-
bench: pytest -m 'benchmark' -vs {posargs}
28+
test: pytest -m 'not benchmark' --ignore=test/client --cov=ovirt_imageio --durations=10 {posargs}
29+
bench: pytest -m 'benchmark' -vs --ignore=test/client {posargs}
30+
31+
[testenv:client]
32+
setenv =
33+
CLIENT_TEST_CONF = {env:CLIENT_TEST_CONF:{toxinidir}/test/client/client_tests.conf}
34+
deps =
35+
pytest
36+
pytest-timeout
37+
pyyaml
38+
ovirt-engine-sdk-python
39+
commands =
40+
pytest -vs --timeout 200 {posargs} test/client
3041

3142
[testenv:flake8]
3243
sitepackages = False

0 commit comments

Comments
 (0)