Skip to content

Commit b05c430

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 ffa7337 commit b05c430

File tree

4 files changed

+174
-3
lines changed

4 files changed

+174
-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: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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+
OS_VERSION = 'fedora-36'
23+
24+
log = logging.getLogger("test")
25+
26+
27+
class ClientError(Exception):
28+
pass
29+
30+
31+
def create_disk(path, fmt, os_version=OS_VERSION):
32+
env = os.environ.copy()
33+
env['LIBGUESTFS_BACKEND'] = 'direct'
34+
cmd = ['virt-builder', os_version, '--format', fmt, '-o', path]
35+
subprocess.check_call(cmd, env=env)
36+
37+
38+
def run_upload_disk(storage_domain, image, disk_id=None, log_level=None):
39+
# Make sure it runs with the same tox environment executable
40+
cmd = [sys.executable, './ovirt-img', 'upload-disk', '-c', 'test']
41+
cmd.extend(['-s', storage_domain])
42+
if log_level:
43+
cmd.extend(['--log-level', log_level])
44+
if disk_id:
45+
cmd.extend(['--disk-id', disk_id])
46+
cmd.append(image)
47+
try:
48+
subprocess.run(cmd, check=True)
49+
except subprocess.CalledProcessError as exc:
50+
raise ClientError(f'Client Error: {exc}') from exc
51+
52+
53+
def run_download_disk(disk_id, image, log_level=None):
54+
# Make sure it runs with the same tox environment executable
55+
cmd = [sys.executable, './ovirt-img', 'download-disk', '-c', 'test']
56+
if log_level:
57+
cmd.extend(['--log-level', log_level])
58+
cmd.extend([disk_id, image])
59+
try:
60+
subprocess.run(cmd, check=True)
61+
except subprocess.CalledProcessError as exc:
62+
raise ClientError(f'Client Error: {exc}') from exc
63+
64+
65+
def remove_disk(conf, sd_name, disk_id):
66+
connection = sdk.Connection(
67+
url=f'{conf["engine_url"]}/ovirt-engine/api',
68+
username=conf["username"],
69+
password=conf["password"],
70+
ca_file=conf["cafile"]
71+
)
72+
with contextlib.closing(connection):
73+
sd_service = connection.system_service().storage_domains_service()
74+
found_sd = sd_service.list(search=f'name={sd_name}')
75+
if not found_sd:
76+
raise RuntimeError(f"Couldn't find storage domain {sd_name}")
77+
78+
sd = found_sd[0]
79+
sd_service = sd_service.storage_domain_service(sd.id)
80+
sd_service.disks_service().disk_service(disk_id).remove()
81+
82+
83+
@pytest.mark.parametrize("fmt", ["raw", "qcow2"])
84+
def test_upload_download(config, tmpdir, fmt):
85+
image = os.path.join(tmpdir, f'image.{fmt}')
86+
create_disk(image, fmt)
87+
test_config = config["tests"]["upload-download"]
88+
for sd_name in test_config.get("storage-domains", []):
89+
disk_id = str(uuid.uuid4())
90+
try:
91+
log.info("Upload %s image to SD %s", fmt, sd_name)
92+
run_upload_disk(sd_name, image, disk_id)
93+
down_img = os.path.join(tmpdir, f'downloaded.{fmt}')
94+
log.info("Download image %s", disk_id)
95+
run_download_disk(disk_id, down_img)
96+
log.info("Comparing images")
97+
qemu_img.compare(image, down_img)
98+
except ClientError as exc:
99+
log.error("%s", exc)
100+
# Skip disk cleanup if client failed
101+
return
102+
finally:
103+
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)