diff --git a/test/functional/api/cas/git.py b/test/functional/api/cas/git.py index 1ee65cd7f..84eee6daf 100644 --- a/test/functional/api/cas/git.py +++ b/test/functional/api/cas/git.py @@ -7,6 +7,7 @@ from core.test_run import TestRun from connection.local_executor import LocalExecutor +from test_utils.output import CmdException def get_current_commit_hash(from_dut: bool = False): diff --git a/test/functional/api/cas/installer.py b/test/functional/api/cas/installer.py index 7dbec614c..b95a60919 100644 --- a/test/functional/api/cas/installer.py +++ b/test/functional/api/cas/installer.py @@ -3,99 +3,146 @@ # SPDX-License-Identifier: BSD-3-Clause-Clear # +from datetime import timedelta -import logging - -from tests import conftest +from api.cas.cas_module import CasModule from core.test_run import TestRun -from api.cas import git -from api.cas import cas_module +from api.cas import cas_module, git +from test_tools.rpm import Rpm from test_utils import os_utils from test_utils.output import CmdException -def rsync_opencas_sources(): - TestRun.LOGGER.info("Copying Open CAS repository to DUT") - TestRun.executor.rsync_to( - f"{TestRun.usr.repo_dir}/", - f"{TestRun.usr.working_dir}/", - exclude_list=["test/functional/results/"], - delete=True) - - -def _clean_opencas_repo(): - TestRun.LOGGER.info("Cleaning Open CAS repo") - output = TestRun.executor.run( - f"cd {TestRun.usr.working_dir} && " - "make distclean") - if output.exit_code != 0: - raise CmdException("make distclean command executed with nonzero status", output) - - -def build_opencas(): - TestRun.LOGGER.info("Building Open CAS") - output = TestRun.executor.run( - f"cd {TestRun.usr.working_dir} && " - "./configure && " - "make -j") - if output.exit_code != 0: - raise CmdException("Make command executed with nonzero status", output) - - -def install_opencas(): - TestRun.LOGGER.info("Installing Open CAS") - output = TestRun.executor.run( - f"cd {TestRun.usr.working_dir} && " - f"make install") - if output.exit_code != 0: - raise CmdException("Error while installing Open CAS", output) - - TestRun.LOGGER.info("Check if casadm is properly installed.") - output = TestRun.executor.run("casadm -V") - if output.exit_code != 0: - raise CmdException("'casadm -V' command returned an error", output) - else: - TestRun.LOGGER.info(output.stdout) +class Installer: + @staticmethod + def rsync_opencas(): + TestRun.LOGGER.info("Copying OpenCAS repository to DUT") + Installer._rsync_opencas(TestRun.usr.repo_dir) + + @staticmethod + def _rsync_opencas(source: str, timeout: timedelta = timedelta(minutes=5)): + TestRun.executor.rsync_to( + f"{source}/", + f"{TestRun.usr.working_dir}/", + exclude_list=["test/functional/results/"], + delete=True, + timeout=timeout + ) + + @staticmethod + def _clean_opencas_repo(): + TestRun.LOGGER.info("Cleaning Open CAS repo") + output = TestRun.executor.run( + f"cd {TestRun.usr.working_dir} && " + "make distclean") + if output.exit_code != 0: + raise CmdException("Cleaning Open CAS repo executed with nonzero status", output) + @staticmethod + def build_opencas(): + TestRun.LOGGER.info("Building Open CAS") + output = TestRun.executor.run( + f"cd {TestRun.usr.working_dir} && " + "./configure && " + "make -j") + if output.exit_code != 0: + raise CmdException("Make command executed with nonzero status", output) -def set_up_opencas(version=None): - _clean_opencas_repo() + @staticmethod + def install_opencas(): + TestRun.LOGGER.info("Installing Open CAS") + output = TestRun.executor.run( + f"cd {TestRun.usr.working_dir} && " + f"make install") + if output.exit_code != 0 or not Installer._is_casadm_installed(): + raise CmdException("Error while installing Open CAS", output) - if version: - git.checkout_cas_version(version) + @staticmethod + def set_up_opencas(version=None): + Installer._clean_opencas_repo() - build_opencas() + if version: + git.checkout_cas_version(version) - install_opencas() + Installer.build_opencas() + Installer.install_opencas() -def uninstall_opencas(): - TestRun.LOGGER.info("Uninstalling Open CAS") - output = TestRun.executor.run("casadm -V") - if output.exit_code != 0: - raise CmdException("Open CAS is not properly installed", output) - else: - TestRun.executor.run( - f"cd {TestRun.usr.working_dir} && " - f"make uninstall") + @staticmethod + def uninstall_opencas(): + TestRun.LOGGER.info("Uninstalling Open CAS") + output = TestRun.executor.run(f"cd {TestRun.usr.working_dir} && make uninstall") if output.exit_code != 0: raise CmdException("There was an error during uninstall process", output) - -def reinstall_opencas(version=None): - if check_if_installed(): - uninstall_opencas() - set_up_opencas(version) - - -def check_if_installed(): - TestRun.LOGGER.info("Check if Open-CAS-Linux is installed") - output = TestRun.executor.run("which casadm") - modules_loaded = os_utils.is_kernel_module_loaded(cas_module.CasModule.cache.value) - - if output.exit_code == 0 and modules_loaded: - TestRun.LOGGER.info("CAS is installed") - - return True - TestRun.LOGGER.info("CAS not installed") - return False + @staticmethod + def reinstall_opencas(version=None): + if Installer.check_if_installed(): + Installer.uninstall_opencas() + Installer.set_up_opencas(version) + + @staticmethod + def check_if_installed(): + TestRun.LOGGER.info("Check if Open-CAS-Linux is installed") + casadm_loaded = Installer._is_casadm_installed() + modules_loaded = os_utils.is_kernel_module_loaded(cas_module.CasModule.cache.value) + + if casadm_loaded and modules_loaded: + TestRun.LOGGER.info("CAS is installed") + return True + + TestRun.LOGGER.info("CAS not installed") + return False + + @staticmethod + def _is_casadm_installed(): + TestRun.LOGGER.info("Check if 'casadm' is properly installed.") + output = TestRun.executor.run("casadm -V") + if output.exit_code != 0: + return False + else: + TestRun.LOGGER.info(output.stdout) + return True + + +class RpmInstaller(Installer): + @staticmethod + def rsync_opencas(): + if TestRun.usr.rpm_dir is not None: + TestRun.LOGGER.info("Copying OpenCAS RPM package to DUT") + Installer._rsync_opencas(TestRun.usr.rpm_dir) + else: + Installer.rsync_opencas() + + @staticmethod + def set_up_opencas(version=None): + if not TestRun.usr.rpm_dir: + Installer._clean_opencas_repo() + + if version: + git.checkout_cas_version(version) + + rpm = Rpm("open-cas-linux") + + if TestRun.usr.rpm_dir is not None: + rpm.packages_dir = TestRun.usr.rpm_dir + else: + rpm.make_rpm(TestRun.usr.working_dir) + + rpm.update_packages_to_install() + rpm.install_packages() + os_utils.load_kernel_module(CasModule.cache.value) + + @staticmethod + def uninstall_opencas(): + TestRun.LOGGER.info("Uninstalling OpenCAS") + if Rpm.is_package_installed("open-cas-linux"): + Rpm("open-cas-linux").uninstall_packages() + else: + Installer.uninstall_opencas() + + @staticmethod + def reinstall_opencas(version=None): + if Installer.check_if_installed(): + RpmInstaller.uninstall_opencas() + RpmInstaller.set_up_opencas(version) diff --git a/test/functional/config/example_dut_config.yml b/test/functional/config/example_dut_config.yml index 619849ece..e77e9ff52 100644 --- a/test/functional/config/example_dut_config.yml +++ b/test/functional/config/example_dut_config.yml @@ -14,6 +14,12 @@ type: "local" allow_disk_autoselect: False working_dir: "/tmp/open-cas-linux/" +# Option below is used only, when CLI flag '--rpm_install' is on. When the flag is on +# and a path is not given, framework would create RPM packages from sources +# in default place (working_dir/packages/) + +# rpm_dir: "path_to_RPM_packages" + disks: - path: "/dev/device_name1" # disk device path serial: "ABC" # disk serial number diff --git a/test/functional/tests/conftest.py b/test/functional/tests/conftest.py index a103f1550..16af6a1f0 100644 --- a/test/functional/tests/conftest.py +++ b/test/functional/tests/conftest.py @@ -14,9 +14,8 @@ sys.path.append(os.path.join(os.path.dirname(__file__), "../test-framework")) from core.test_run_utils import TestRun -from api.cas import installer -from api.cas import casadm -from api.cas import git +from api.cas import casadm, git +from api.cas.installer import Installer, RpmInstaller from test_utils.os_utils import Udev, kill_all_io from test_tools.disk_utils import PartitionTable, create_partition_table from test_tools.device_mapper import DeviceMapper @@ -25,9 +24,10 @@ class Opencas(metaclass=Singleton): - def __init__(self, repo_dir, working_dir): + def __init__(self, repo_dir, working_dir, rpm_dir): self.repo_dir = repo_dir self.working_dir = working_dir + self.rpm_dir = rpm_dir self.already_updated = False @@ -72,7 +72,9 @@ def pytest_runtest_setup(item): TestRun.usr = Opencas( repo_dir=os.path.join(os.path.dirname(__file__), "../../.."), - working_dir=dut_config['working_dir']) + working_dir=dut_config['working_dir'], + rpm_dir=dut_config.get('rpm_dir') + ) TestRun.LOGGER.info(f"DUT info: {TestRun.dut}") @@ -102,7 +104,7 @@ def pytest_runtest_teardown(): Udev.enable() kill_all_io() unmount_cas_devices() - if installer.check_if_installed(): + if Installer.check_if_installed(): casadm.remove_all_detached_cores() casadm.stop_all_caches() from api.cas.init_config import InitConfig @@ -120,6 +122,7 @@ def pytest_runtest_teardown(): def pytest_configure(config): + add_marks(config) TestRun.configure(config) @@ -133,6 +136,7 @@ def pytest_addoption(parser): parser.addoption("--log-path", action="store", default=f"{os.path.join(os.path.dirname(__file__), '../results')}") parser.addoption("--force-reinstall", action="store_true", default=False) + parser.addoption("--rpm-install", action="store_true", default=False) def unmount_cas_devices(): @@ -161,6 +165,10 @@ def get_force_param(item): return item.config.getoption("--force-reinstall") +def get_rpm_param(item): + return item.config.getoption("--rpm-install") + + def base_prepare(item): with TestRun.LOGGER.step("Cleanup before test"): TestRun.executor.run("pkill --signal=SIGKILL fsck") @@ -168,7 +176,11 @@ def base_prepare(item): kill_all_io() DeviceMapper.remove_all() - if installer.check_if_installed(): + uninstall_cas = list(TestRun.item.iter_markers(name="uninstall_cas")) + installer = RpmInstaller if get_rpm_param(item) else Installer + opencas_installed = installer.check_if_installed() + + if opencas_installed: try: from api.cas.init_config import InitConfig InitConfig.create_default_init_config() @@ -176,21 +188,34 @@ def base_prepare(item): casadm.stop_all_caches() casadm.remove_all_detached_cores() except Exception: - pass # TODO: Reboot DUT if test is executed remotely + if TestRun.executor.is_remote(): + TestRun.executor.reboot() for disk in TestRun.dut.disks: disk.umount_all_partitions() disk.remove_partitions() create_partition_table(disk, PartitionTable.gpt) - if get_force_param(item) and not TestRun.usr.already_updated: - installer.rsync_opencas_sources() + # sources should be up-to-date on DUT even if installation is skipped + installer.rsync_opencas() + + if uninstall_cas: + if opencas_installed: + RpmInstaller.uninstall_opencas() + elif get_force_param(item) and not TestRun.usr.already_updated: installer.reinstall_opencas() - elif not installer.check_if_installed(): - installer.rsync_opencas_sources() + elif not opencas_installed and not uninstall_cas: installer.set_up_opencas() + TestRun.usr.already_updated = True TestRun.LOGGER.add_build_info(f'Commit hash:') TestRun.LOGGER.add_build_info(f"{git.get_current_commit_hash()}") TestRun.LOGGER.add_build_info(f'Commit message:') TestRun.LOGGER.add_build_info(f'{git.get_current_commit_message()}') + + +def add_marks(config): + config.addinivalue_line( + "markers", + "uninstall_cas: don't install OpenCAS and if already installed, uninstall it" + ) diff --git a/test/functional/tests/install/test_install_rpm.py b/test/functional/tests/install/test_install_rpm.py new file mode 100644 index 000000000..1609bc568 --- /dev/null +++ b/test/functional/tests/install/test_install_rpm.py @@ -0,0 +1,46 @@ +# +# Copyright(c) 2020 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause-Clear +# + +import pytest + +from api.cas.cas_module import CasModule +from core.test_run import TestRun +from test_tools.rpm import Rpm +from test_utils import os_utils +from api.cas.installer import RpmInstaller + + +@pytest.mark.remote_only() +@pytest.mark.uninstall_cas() +def test_install_from_rpm(): + """ + title: Test for installing OpenCAS from RPM + description: | + Check if OpenCAS could be installed from RPM and then uninstalled. + pass_criteria: + - OpenCAS installs successfully + - OpenCAS uninstalls successfully + """ + with TestRun.step("Download and install OpenCAS from RPM."): + RpmInstaller.rsync_opencas() + RpmInstaller.set_up_opencas() + + with TestRun.step("Load OpenCAS modules."): + output = os_utils.load_kernel_module(CasModule.cache.value) + if output.exit_code != 0: + TestRun.fail(f"Loading {CasModule.cache.value} module failed.") + + with TestRun.step("Check if OpenCAS is installed correctly from RPM."): + if not RpmInstaller.check_if_installed(): + TestRun.fail("OpenCAS is not installed correctly.") + + with TestRun.step("Uninstall OpenCAS from RPM."): + RpmInstaller.uninstall_opencas() + + with TestRun.step("Check if OpenCAS is uninstalled correctly."): + if RpmInstaller.check_if_installed(): + TestRun.fail("OpenCAS should be uninstalled.") + if Rpm.is_package_installed("open-cas-linux"): + TestRun.fail("OpenCAS should be uninstalled from RPM.") diff --git a/test/functional/tests/stress/test_kedr.py b/test/functional/tests/stress/test_kedr.py index f3eab3b1e..1100d3a43 100644 --- a/test/functional/tests/stress/test_kedr.py +++ b/test/functional/tests/stress/test_kedr.py @@ -4,11 +4,11 @@ # import pytest - from datetime import timedelta from test_tools.kedr import Kedr, KedrProfile -from api.cas import cas_module, installer, casadm +from api.cas import cas_module, casadm +from api.cas.installer import Installer from core.test_run import TestRun from test_utils import os_utils from test_utils.size import Size, Unit @@ -20,6 +20,7 @@ mountpoint = "/tmp/cas1-1" + @pytest.fixture(scope="module") def install_kedr(): TestRun.LOGGER.info("Checking if kedr is installed") @@ -31,7 +32,7 @@ def install_kedr(): @pytest.fixture(scope="function") def unload_modules(): TestRun.LOGGER.info("Check if CAS is installed") - if installer.check_if_installed(): + if Installer.check_if_installed(): TestRun.LOGGER.info("Unloading modules") cas_module.unload_all_cas_modules()