From 38ff68588078af1664787e20256ffba3ae166489 Mon Sep 17 00:00:00 2001 From: Albert Esteve Date: Nov 27 2022 14:32:44 +0000 Subject: userstorage: replace by PyPI userstorage Remove the outdated version of userstorage that is stored locally at tests/storage.py The userstorage library is required to create the storage before running the tests with tox, and also in the test virtual environment. In order to satisfy this, add a requirements.txt to the root folder to obtain the latests userstorage version from PyPI, and add it as a tox dependency for tests. Behaviour for missing storage and folder structure remains as originally intended. Fixture is adapted to new style so that is uses setup and teardown before and after every test, respectively. Signed-off-by: Albert Esteve --- diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2dfdbcd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +tox +userstorage>=0.5.1 diff --git a/tests/conftest.py b/tests/conftest.py index b40852b..79c514b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,13 +9,17 @@ Fixtures for sanlock testing. """ from __future__ import absolute_import -import os - import pytest +import userstorage -from . import storage from . import util +# Mark tests with skip if userstorage is missing +userstorage.missing_handler = pytest.skip + +# Requires relative path from tox basedir +BACKENDS = userstorage.load_config("./tests/storage.py").BACKENDS + class SanlockIsRunning(Exception): """ Raised if sanlock running when it should not """ @@ -38,8 +42,8 @@ def sanlock_daemon(): @pytest.fixture(params=[ - pytest.param(storage.BLOCK, id="block"), - pytest.param(storage.FILE, id="file"), + BACKENDS["block"], + BACKENDS["file"], ]) def user_4k_path(request): """ @@ -48,11 +52,9 @@ def user_4k_path(request): If storage is not available, skip the tests. """ - if not os.path.exists(request.param): - pytest.skip( - "user storage available - run 'python tests/strorage.py setup' " - "to enable 4k storage tests") - return request.param + backend = request.param + with backend: + yield backend.path @pytest.fixture diff --git a/tests/storage.py b/tests/storage.py index 0fe6f56..0b12e47 100644 --- a/tests/storage.py +++ b/tests/storage.py @@ -8,145 +8,28 @@ storage - provide storage for sanlock tests. """ -import argparse -import errno -import logging -import os -import subprocess +from userstorage import File, Mount, LoopDevice -BASE_DIR = "/var/tmp/sanlock-storage" -MOUNTPOINT = os.path.join(BASE_DIR, "mnt") - -# For testing sanlock with 4k block device. -LOOP1 = os.path.join(BASE_DIR, "loop1") -BACKING1 = os.path.join(BASE_DIR, "backing1") - -# For testing sanlock with a filesystem backed by 4k block device. -LOOP2 = os.path.join(BASE_DIR, "loop2") -BACKING2 = os.path.join(BASE_DIR, "backing2") - -# Test paths. -BLOCK = LOOP1 -FILE = os.path.join(MOUNTPOINT, "file") - -log = logging.getLogger("storage") - - -def main(): - parser = argparse.ArgumentParser( - description='Storage helper for sanlock tests') - parser.add_argument("command", choices=["setup", "teardown"]) - args = parser.parse_args() - - logging.basicConfig(level=logging.INFO, format="storage: %(message)s") - - if args.command == "setup": - setup() - elif args.command == "teardown": - teardown() - - -def setup(): - create_dir(BASE_DIR) - - if not os.path.exists(LOOP1): - create_loop_device(LOOP1, BACKING1) - - if not os.path.exists(LOOP2): - create_loop_device(LOOP2, BACKING2) - create_dir(MOUNTPOINT) - create_filesystem(LOOP2, MOUNTPOINT) - - # Sanlock allocates spaces as needed. - with open(FILE, "wb") as f: - f.truncate(0) - - -def teardown(): - if is_mounted(MOUNTPOINT): - remove_filesystem(MOUNTPOINT) - - if os.path.exists(LOOP2): - remove_loop_device(LOOP2, BACKING2) - - if os.path.exists(LOOP1): - remove_loop_device(LOOP1, BACKING1) - - -def create_loop_device(link_path, backing_file, size=1024**3, - sector_size=4096): - log.info("Creating loop device %s", link_path) - - with open(backing_file, "wb") as f: - f.truncate(size) - - out = subprocess.check_output([ - "sudo", - "losetup", - "-f", backing_file, - "--sector-size", str(sector_size), - "--show", - ]) - - device = out.decode("utf-8").strip() - - # Remove stale symlink. - if os.path.islink(link_path): - os.unlink(link_path) - - os.symlink(device, link_path) - chown(link_path) - - -def remove_loop_device(link_path, backing_file): - log.info("Removing loop device %s", link_path) - - subprocess.check_call(["sudo", "losetup", "-d", link_path]) - remove_file(link_path) - remove_file(backing_file) - - -def create_filesystem(device, mountpoint): - log.info("Creating filesystem %s", mountpoint) - - subprocess.check_call(["sudo", "mkfs.xfs", "-q", device]) - subprocess.check_call(["sudo", "mount", device, mountpoint]) - chown(mountpoint) - - -def remove_filesystem(mountpoint): - log.info("Removing filesystem %s", mountpoint) - subprocess.check_call(["sudo", "umount", mountpoint]) - - -def is_mounted(mountpoint): - with open("/proc/self/mounts") as f: - for line in f: - if mountpoint in line: - return True - return False - - -def chown(path): - user_group = "%(USER)s:%(USER)s" % os.environ - subprocess.check_call(["sudo", "chown", user_group, path]) - - -def create_dir(path): - try: - os.makedirs(path) - except EnvironmentError as e: - if e.errno != errno.EEXIST: - raise - - -def remove_file(path): - try: - os.remove(path) - except EnvironmentError as e: - if e.errno != errno.ENOENT: - raise +GiB = 1024**3 +BASE_DIR = "/var/tmp/sanlock-storage" -if __name__ == "__main__": - main() +BACKENDS = { + + "file": + File( + Mount( + LoopDevice( + base_dir=BASE_DIR, + name="file", + size=GiB, + sector_size=4096))), + + "block": + LoopDevice( + base_dir=BASE_DIR, + name="loop", + size=GiB, + sector_size=4096), + +} diff --git a/tox.ini b/tox.ini index 8847b34..c0cf5a1 100644 --- a/tox.ini +++ b/tox.ini @@ -17,6 +17,7 @@ setenv = whitelist_externals = make deps = pytest + userstorage>=0.5.1 commands = py{36,37,38,39,310}: make BUILDARGS="--build-lib={envsitepackagesdir}" pytest {posargs}