Skip to content

Commit 33d145b

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. Fixes: oVirt#124 Signed-off-by: Albert Esteve <aesteve@redhat.com>
1 parent ed6e07c commit 33d145b

File tree

4 files changed

+162
-1
lines changed

4 files changed

+162
-1
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: 11 additions & 1 deletion
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
@@ -28,6 +28,16 @@ commands =
2828
test: pytest -m 'not benchmark' --cov=ovirt_imageio --durations=10 {posargs}
2929
bench: pytest -m 'benchmark' -vs {posargs}
3030

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+
ovirt-engine-sdk-python
38+
commands =
39+
pytest -vs --timeout 200 {posargs} test/client
40+
3141
[testenv:flake8]
3242
sitepackages = False
3343
deps =

0 commit comments

Comments
 (0)