diff --git a/test/functional/test-framework/__init__.py b/test/functional/test-framework/__init__.py
deleted file mode 100644
index dce958c..0000000
--- a/test/functional/test-framework/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/test/functional/test-framework/connection/__init__.py b/test/functional/test-framework/connection/__init__.py
deleted file mode 100644
index dce958c..0000000
--- a/test/functional/test-framework/connection/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/test/functional/test-framework/connection/base_executor.py b/test/functional/test-framework/connection/base_executor.py
deleted file mode 100644
index f47867e..0000000
--- a/test/functional/test-framework/connection/base_executor.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import time
-from datetime import timedelta
-
-from core.test_run import TestRun
-from test_utils.output import CmdException
-
-
-class BaseExecutor:
- def _execute(self, command, timeout):
- raise NotImplementedError()
-
- def _rsync(self, src, dst, delete, symlinks, checksum, exclude_list, timeout,
- dut_to_controller):
- raise NotImplementedError()
-
- def rsync_to(self, src, dst, delete=False, symlinks=False, checksum=False, exclude_list=[],
- timeout: timedelta = timedelta(seconds=90)):
- return self._rsync(src, dst, delete, symlinks, checksum, exclude_list, timeout, False)
-
- def rsync_from(self, src, dst, delete=False, symlinks=False, checksum=False, exclude_list=[],
- timeout: timedelta = timedelta(seconds=90)):
- return self._rsync(src, dst, delete, symlinks, checksum, exclude_list, timeout, True)
-
- def is_remote(self):
- return False
-
- def is_active(self):
- return True
-
- def wait_for_connection(self, timeout: timedelta = None):
- pass
-
- def run(self, command, timeout: timedelta = timedelta(minutes=30)):
- if TestRun.dut and TestRun.dut.env:
- command = f"{TestRun.dut.env} && {command}"
- command_id = TestRun.LOGGER.get_new_command_id()
- ip_info = TestRun.dut.ip if len(TestRun.duts) > 1 else ""
- TestRun.LOGGER.write_command_to_command_log(command, command_id, info=ip_info)
- output = self._execute(command, timeout)
- TestRun.LOGGER.write_output_to_command_log(output, command_id)
- return output
-
- def run_in_background(self,
- command,
- stdout_redirect_path="/dev/null",
- stderr_redirect_path="/dev/null"):
- command += f" > {stdout_redirect_path} 2> {stderr_redirect_path} &echo $!"
- output = self.run(command)
-
- if output is not None:
- return int(output.stdout)
-
- def wait_cmd_finish(self, pid: int, timeout: timedelta = timedelta(minutes=30)):
- self.run(f"tail --pid={pid} -f /dev/null", timeout)
-
- def check_if_process_exists(self, pid: int):
- output = self.run(f"ps aux | awk '{{print $2 }}' | grep ^{pid}$", timedelta(seconds=10))
- return True if output.exit_code == 0 else False
-
- def kill_process(self, pid: int):
- # TERM signal should be used in preference to the KILL signal, since a
- # process may install a handler for the TERM signal in order to perform
- # clean-up steps before terminating in an orderly fashion.
- self.run(f"kill -s SIGTERM {pid} &> /dev/null")
- time.sleep(3)
- self.run(f"kill -s SIGKILL {pid} &> /dev/null")
-
- def run_expect_success(self, command, timeout: timedelta = timedelta(minutes=30)):
- output = self.run(command, timeout)
- if output.exit_code != 0:
- raise CmdException(f"Exception occurred while trying to execute '{command}' command.",
- output)
- return output
-
- def run_expect_fail(self, command, timeout: timedelta = timedelta(minutes=30)):
- output = self.run(command, timeout)
- if output.exit_code == 0:
- raise CmdException(f"Command '{command}' executed properly but error was expected.",
- output)
- return output
diff --git a/test/functional/test-framework/connection/dummy_executor.py b/test/functional/test-framework/connection/dummy_executor.py
deleted file mode 100644
index 0001272..0000000
--- a/test/functional/test-framework/connection/dummy_executor.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from connection.base_executor import BaseExecutor
-
-
-class DummyExecutor(BaseExecutor):
- def _execute(self, command, timeout=None):
- print(command)
-
- def _rsync(self, src, dst, delete, symlinks, checksum, exclude_list, timeout,
- dut_to_controller):
- print(f'COPY FROM "{src}" TO "{dst}"')
diff --git a/test/functional/test-framework/connection/local_executor.py b/test/functional/test-framework/connection/local_executor.py
deleted file mode 100644
index fae9e28..0000000
--- a/test/functional/test-framework/connection/local_executor.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import subprocess
-from datetime import timedelta
-
-from connection.base_executor import BaseExecutor
-from test_utils.output import Output
-
-
-class LocalExecutor(BaseExecutor):
- def _execute(self, command, timeout):
- completed_process = subprocess.run(
- command,
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- timeout=timeout.total_seconds())
-
- return Output(completed_process.stdout,
- completed_process.stderr,
- completed_process.returncode)
-
- def _rsync(self, src, dst, delete=False, symlinks=False, checksum=False, exclude_list=[],
- timeout: timedelta = timedelta(seconds=90), dut_to_controller=False):
- options = []
-
- if delete:
- options.append("--delete")
- if symlinks:
- options.append("--links")
- if checksum:
- options.append("--checksum")
-
- for exclude in exclude_list:
- options.append(f"--exclude {exclude}")
-
- completed_process = subprocess.run(
- f'rsync -r {src} {dst} {" ".join(options)}',
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- timeout=timeout.total_seconds())
-
- if completed_process.returncode:
- raise Exception(f"rsync failed:\n{completed_process}")
diff --git a/test/functional/test-framework/connection/ssh_executor.py b/test/functional/test-framework/connection/ssh_executor.py
deleted file mode 100644
index 237420f..0000000
--- a/test/functional/test-framework/connection/ssh_executor.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import socket
-import subprocess
-import paramiko
-
-from datetime import timedelta, datetime
-from connection.base_executor import BaseExecutor
-from core.test_run import TestRun
-from test_utils.output import Output
-
-
-class SshExecutor(BaseExecutor):
- def __init__(self, ip, username, port=22):
- self.ip = ip
- self.user = username
- self.port = port
- self.ssh = paramiko.SSHClient()
- self._check_config_for_reboot_timeout()
-
- def __del__(self):
- self.ssh.close()
-
- def connect(self, user=None, port=None,
- timeout: timedelta = timedelta(seconds=30)):
- user = user or self.user
- port = port or self.port
- self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- try:
- self.ssh.connect(self.ip, username=user,
- port=port, timeout=timeout.total_seconds(),
- banner_timeout=timeout.total_seconds())
- except paramiko.AuthenticationException as e:
- raise paramiko.AuthenticationException(
- f"Authentication exception occurred while trying to connect to DUT. "
- f"Please check your SSH key-based authentication.\n{e}")
- except (paramiko.SSHException, socket.timeout) as e:
- raise ConnectionError(f"An exception of type '{type(e)}' occurred while trying to "
- f"connect to {self.ip}.\n {e}")
-
- def disconnect(self):
- try:
- self.ssh.close()
- except Exception:
- raise Exception(f"An exception occurred while trying to disconnect from {self.ip}")
-
- def _execute(self, command, timeout):
- try:
- (stdin, stdout, stderr) = self.ssh.exec_command(command,
- timeout=timeout.total_seconds())
- except paramiko.SSHException as e:
- raise ConnectionError(f"An exception occurred while executing command '{command}' on"
- f" {self.ip}\n{e}")
-
- return Output(stdout.read(), stderr.read(), stdout.channel.recv_exit_status())
-
- def _rsync(self, src, dst, delete=False, symlinks=False, checksum=False, exclude_list=[],
- timeout: timedelta = timedelta(seconds=90), dut_to_controller=False):
- options = []
-
- if delete:
- options.append("--delete")
- if symlinks:
- options.append("--links")
- if checksum:
- options.append("--checksum")
-
- for exclude in exclude_list:
- options.append(f"--exclude {exclude}")
-
- src_to_dst = f"{self.user}@{self.ip}:{src} {dst} " if dut_to_controller else\
- f"{src} {self.user}@{self.ip}:{dst} "
-
- try:
- completed_process = subprocess.run(
- f'rsync -r -e "ssh -p {self.port} '
- f'-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" '
- + src_to_dst + f'{" ".join(options)}',
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- timeout=timeout.total_seconds())
- except Exception as e:
- TestRun.LOGGER.exception(f"Exception occurred during rsync process. "
- f"Please check your SSH key-based authentication.\n{e}")
-
- if completed_process.returncode:
- raise Exception(f"rsync failed:\n{completed_process}")
-
- def is_remote(self):
- return True
-
- def _check_config_for_reboot_timeout(self):
- if "reboot_timeout" in TestRun.config.keys():
- self._parse_timeout_to_int()
- else:
- self.reboot_timeout = None
-
- def _parse_timeout_to_int(self):
- self.reboot_timeout = int(TestRun.config["reboot_timeout"])
- if self.reboot_timeout < 0:
- raise ValueError("Reboot timeout cannot be negative.")
-
- def reboot(self):
- self.run("reboot")
- self.wait_for_connection_loss()
- self.wait_for_connection(timedelta(seconds=self.reboot_timeout)) \
- if self.reboot_timeout is not None else self.wait_for_connection()
-
- def is_active(self):
- try:
- self.ssh.exec_command('', timeout=5)
- return True
- except Exception:
- return False
-
- def wait_for_connection(self, timeout: timedelta = timedelta(minutes=10)):
- start_time = datetime.now()
- with TestRun.group("Waiting for DUT ssh connection"):
- while start_time + timeout > datetime.now():
- try:
- self.connect()
- return
- except paramiko.AuthenticationException:
- raise
- except Exception:
- continue
- raise ConnectionError("Timeout occurred while trying to establish ssh connection")
-
- def wait_for_connection_loss(self, timeout: timedelta = timedelta(minutes=1)):
- with TestRun.group("Waiting for DUT ssh connection loss"):
- end_time = datetime.now() + timeout
- while end_time > datetime.now():
- self.disconnect()
- try:
- self.connect(timeout=timedelta(seconds=5))
- except Exception:
- return
- raise ConnectionError("Timeout occurred before ssh connection loss")
diff --git a/test/functional/test-framework/core/__init__.py b/test/functional/test-framework/core/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/core/pair_testing.py b/test/functional/test-framework/core/pair_testing.py
deleted file mode 100644
index b7eea73..0000000
--- a/test/functional/test-framework/core/pair_testing.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# The MIT License (MIT)
-#
-# Copyright (c) 2004-2020 Holger Krekel and others
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy of
-# this software and associated documentation files (the "Software"), to deal in
-# the Software without restriction, including without limitation the rights to
-# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is furnished to do
-# so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-
-from itertools import product, combinations
-import random
-
-from core.test_run import TestRun
-
-def testcase_id(param_set):
- if len(param_set.values) == 1:
- return param_set.values[0]
-
- return "-".join([str(value) for value in param_set.values])
-
-
-def generate_pair_testing_testcases(*argvals):
- """
- Generate test_cases from provided argument values lists in such way that each possible
- (argX, argY) pair will be used.
- """
- # if only one argument is used, yield from it
- if len(argvals) == 1:
- for val in argvals[0]:
- yield (val,)
-
- # append argument index to argument values list to avoid confusion when there are two arguments
- # with the same type
- for i, arg in enumerate(argvals):
- for j, val in enumerate(arg):
- arg[j] = (i, val)
-
- # generate all possible test cases
- all_test_cases = list(product(*argvals))
- random.seed(TestRun.random_seed)
- random.shuffle(all_test_cases)
-
- used_pairs = set()
- for tc in all_test_cases:
- current_pairs = set(combinations(tc, 2))
- # if cardinality of (current_pairs & used_pairs) is lesser than cardinality of current_pairs
- # it means not all argument pairs in this tc have been used. return current tc
- # and update used_pairs set
- if len(current_pairs & used_pairs) != len(current_pairs):
- used_pairs.update(current_pairs)
- # unpack testcase by deleting argument index
- yield list(list(zip(*tc))[1])
-
-
-def register_testcases(metafunc, argnames, argvals):
- """
- Add custom parametrization test cases. Based on metafunc's parametrize method.
- """
- from _pytest.python import CallSpec2, _find_parametrized_scope
- from _pytest.mark import ParameterSet
- from _pytest.fixtures import scope2index
-
- parameter_sets = [ParameterSet(values=val, marks=[], id=None) for val in argvals]
- metafunc._validate_if_using_arg_names(argnames, False)
-
- arg_value_types = metafunc._resolve_arg_value_types(argnames, False)
-
- ids = [testcase_id(param_set) for param_set in parameter_sets]
-
- scope = _find_parametrized_scope(argnames, metafunc._arg2fixturedefs, False)
- scopenum = scope2index(scope, descr=f"parametrizex() call in {metafunc.function.__name__}")
-
- calls = []
- for callspec in metafunc._calls or [CallSpec2(metafunc)]:
- for param_index, (param_id, param_set) in enumerate(zip(ids, parameter_sets)):
- newcallspec = callspec.copy()
- newcallspec.setmulti2(
- arg_value_types,
- argnames,
- param_set.values,
- param_id,
- param_set.marks,
- scopenum,
- param_index,
- )
- calls.append(newcallspec)
-
- metafunc._calls = calls
diff --git a/test/functional/test-framework/core/plugins.py b/test/functional/test-framework/core/plugins.py
deleted file mode 100644
index 7d36224..0000000
--- a/test/functional/test-framework/core/plugins.py
+++ /dev/null
@@ -1,124 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import pytest
-import sys
-import importlib
-import signal
-from core.test_run import TestRun
-
-
-class PluginManager:
- def __init__(self, item, config):
- if 'plugins_dir' in config:
- sys.path.append(config['plugins_dir'])
- self.plugins = {}
-
- self.plugins_config = config.get('plugins', {})
-
- self.req_plugins = config.get('req_plugins', {})
- self.opt_plugins = config.get('opt_plugins', {})
-
- self.req_plugins.update(dict(map(lambda mark: (mark.args[0], mark.kwargs),
- item.iter_markers(name="require_plugin"))))
-
- req_plugin_mod = {}
- opt_plugin_mod = {}
-
- for name in self.req_plugins:
- try:
- req_plugin_mod[name] = self.__import_plugin(name)
- except ModuleNotFoundError:
- pytest.skip("Unable to find requested plugin!")
-
- for name in self.opt_plugins:
- try:
- opt_plugin_mod[name] = self.__import_plugin(name)
- except ModuleNotFoundError as e:
- TestRun.LOGGER.debug(
- f"Failed to import '{name}' - optional plugin. " f"Reason: {e}"
- )
- continue
-
- for name, mod in req_plugin_mod.items():
- try:
- self.plugins[name] = mod.plugin_class(
- self.req_plugins[name],
- self.plugins_config.get(name, {}).get("config", {}))
- except Exception:
- pytest.skip(f"Unable to initialize plugin '{name}'")
-
- for name, mod in opt_plugin_mod.items():
- try:
- self.plugins[name] = mod.plugin_class(
- self.opt_plugins[name],
- self.plugins_config.get(name, {}).get("config", {}))
- except Exception as e:
- TestRun.LOGGER.debug(
- f"Failed to initialize '{name}' - optional plugin. " f"Reason: {e}"
- )
- continue
-
- def __import_plugin(self, name):
- provided_by = self.plugins_config.get(name, {}).get("provided_by")
- if provided_by:
- return importlib.import_module(provided_by)
-
- try:
- return importlib.import_module(f"internal_plugins.{name}")
- except ModuleNotFoundError:
- pass
-
- return importlib.import_module(f"external_plugins.{name}")
-
- def hook_pre_setup(self):
- for plugin in self.plugins.values():
- plugin.pre_setup()
-
- def hook_post_setup(self):
- for plugin in self.plugins.values():
- plugin.post_setup()
-
- def hook_teardown(self):
- for plugin in self.plugins.values():
- plugin.teardown()
-
- def get_plugin(self, name):
- if name not in self.plugins:
- raise KeyError("Requested plugin does not exist")
- return self.plugins[name]
-
- def teardown_on_signal(self, sig_id, plugin_name):
- try:
- plugin = self.get_plugin(plugin_name)
- except Exception as e:
- TestRun.LOGGER.warning(
- f"Failed to setup teardown on signal for {plugin_name}. Reason: {e}")
- return
-
- old_sig_handler = None
-
- def signal_handler(sig, frame):
- plugin.teardown()
-
- if old_sig_handler is not None:
- if old_sig_handler == signal.SIG_DFL:
- # In case of SIG_DFL the function pointer points to address 0,
- # which is not a valid address.
- # We have to reset the handler and raise the signal again
- signal.signal(sig, signal.SIG_DFL)
- signal.raise_signal(sig)
- signal.signal(sig, signal_handler)
- elif old_sig_handler == signal.SIG_IGN:
- # SIG_IGN has value 1 (also an invalid address).
- # Here we can just return (do nothing)
- return
- else:
- # When we received neither SIG_IGN nor SIG_DFL, the received value is
- # a valid function pointer and we can call the handler directly
- old_sig_handler()
- signal.signal(sig, old_sig_handler)
-
- old_sig_handler = signal.signal(sig_id, signal_handler)
diff --git a/test/functional/test-framework/core/test_run.py b/test/functional/test-framework/core/test_run.py
deleted file mode 100644
index ae0762e..0000000
--- a/test/functional/test-framework/core/test_run.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-from contextlib import contextmanager
-
-import pytest
-
-from log.logger import Log
-
-
-class Blocked(Exception):
- pass
-
-
-class TestRun:
- dut = None
- executor = None
- LOGGER: Log = None
- plugin_manager = None
- duts = None
- disks = None
-
- @classmethod
- @contextmanager
- def use_dut(cls, dut):
- cls.dut = dut
- cls.config = cls.dut.config
- cls.executor = cls.dut.executor
- cls.plugin_manager = cls.dut.plugin_manager
- cls.disks = cls.dut.req_disks
- yield cls.executor
- cls.disks = None
- cls.plugin_manager = None
- cls.executor = None
- # setting cls.config to None omitted (causes problems in the teardown stage of execution)
- cls.dut = None
-
- @classmethod
- def step(cls, message):
- return cls.LOGGER.step(message)
-
- @classmethod
- def group(cls, message):
- return cls.LOGGER.group(message)
-
- @classmethod
- def iteration(cls, iterable, group_name=None):
- TestRun.LOGGER.start_group(f"{group_name}" if group_name is not None else "Iteration list")
- items = list(iterable)
- for i, item in enumerate(items, start=1):
- cls.LOGGER.start_iteration(f"Iteration {i}/{len(items)}")
- yield item
- TestRun.LOGGER.end_iteration()
- TestRun.LOGGER.end_group()
-
- @classmethod
- def fail(cls, message):
- pytest.fail(message)
-
- @classmethod
- def block(cls, message):
- raise Blocked(message)
diff --git a/test/functional/test-framework/core/test_run_utils.py b/test/functional/test-framework/core/test_run_utils.py
deleted file mode 100644
index a27d018..0000000
--- a/test/functional/test-framework/core/test_run_utils.py
+++ /dev/null
@@ -1,272 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import posixpath
-import random
-import sys
-import traceback
-
-import pytest
-from IPy import IP
-
-import core.test_run
-from connection.local_executor import LocalExecutor
-from connection.ssh_executor import SshExecutor
-from core.pair_testing import generate_pair_testing_testcases, register_testcases
-from core.plugins import PluginManager
-from log.base_log import BaseLogResult
-from storage_devices.disk import Disk
-from test_utils import disk_finder
-from test_utils.dut import Dut
-
-TestRun = core.test_run.TestRun
-
-
-@classmethod
-def __configure(cls, config):
- config.addinivalue_line(
- "markers",
- "require_disk(name, type): require disk of specific type, otherwise skip"
- )
- config.addinivalue_line(
- "markers",
- "require_plugin(name, *kwargs): require specific plugins, otherwise skip"
- )
- config.addinivalue_line(
- "markers",
- "remote_only: run test only in case of remote execution, otherwise skip"
- )
- config.addinivalue_line(
- "markers",
- "os_dependent: run test only if its OS dependent, otherwise skip"
- )
- config.addinivalue_line(
- "markers",
- "multidut(number): test requires a number of different platforms to be executed"
- )
- config.addinivalue_line(
- "markers",
- "parametrizex(argname, argvalues): sparse parametrized testing"
- )
- config.addinivalue_line(
- "markers",
- "CI: marks test for continuous integration pipeline"
- )
-
- cls.random_seed = config.getoption("--random-seed") or random.randrange(sys.maxsize)
- random.seed(cls.random_seed)
-
-
-TestRun.configure = __configure
-
-
-@classmethod
-def __prepare(cls, item, config):
- if not config:
- raise Exception("You need to specify DUT config!")
-
- cls.item = item
- cls.config = config
-
- req_disks = list(map(lambda mark: mark.args, cls.item.iter_markers(name="require_disk")))
- cls.req_disks = dict(req_disks)
- if len(req_disks) != len(cls.req_disks):
- raise Exception("Disk name specified more than once!")
-
-
-TestRun.prepare = __prepare
-
-
-@classmethod
-def __attach_log(cls, log_path, target_name=None):
- if target_name is None:
- target_name = posixpath.basename(log_path)
- if cls.config.get('extra_logs'):
- cls.config["extra_logs"][target_name] = log_path
- else:
- cls.config["extra_logs"] = {target_name: log_path}
-
-
-TestRun.attach_log = __attach_log
-
-
-@classmethod
-def __setup_disk(cls, disk_name, disk_type):
- cls.disks[disk_name] = next(filter(
- lambda disk: disk.disk_type in disk_type.types() and disk not in cls.disks.values(),
- cls.dut.disks
- ), None)
- if not cls.disks[disk_name]:
- pytest.skip("Unable to find requested disk!")
-
-
-TestRun.__setup_disk = __setup_disk
-
-
-@classmethod
-def __setup_disks(cls):
- cls.disks = {}
- items = list(cls.req_disks.items())
- while items:
- resolved, unresolved = [], []
- for disk_name, disk_type in items:
- (resolved, unresolved)[not disk_type.resolved()].append((disk_name, disk_type))
- resolved.sort(
- key=lambda disk: (lambda disk_name, disk_type: disk_type)(*disk)
- )
- for disk_name, disk_type in resolved:
- cls.__setup_disk(disk_name, disk_type)
- items = unresolved
- cls.dut.req_disks = cls.disks
-
-
-TestRun.__setup_disks = __setup_disks
-
-
-@classmethod
-def __presetup(cls):
- cls.plugin_manager = PluginManager(cls.item, cls.config)
- cls.plugin_manager.hook_pre_setup()
-
- if cls.config['type'] == 'ssh':
- try:
- IP(cls.config['ip'])
- except ValueError:
- TestRun.block("IP address from config is in invalid format.")
-
- port = cls.config.get('port', 22)
-
- if 'user' in cls.config:
- cls.executor = SshExecutor(
- cls.config['ip'],
- cls.config['user'],
- port
- )
- else:
- TestRun.block("There is no user given in config.")
- elif cls.config['type'] == 'local':
- cls.executor = LocalExecutor()
- else:
- TestRun.block("Execution type (local/ssh) is missing in DUT config!")
-
-
-TestRun.presetup = __presetup
-
-
-@classmethod
-def __setup(cls):
- if list(cls.item.iter_markers(name="remote_only")):
- if not cls.executor.is_remote():
- pytest.skip()
-
- Disk.plug_all_disks()
- if cls.config.get('allow_disk_autoselect', False):
- cls.config["disks"] = disk_finder.find_disks()
-
- try:
- cls.dut = Dut(cls.config)
- except Exception as ex:
- raise Exception(f"Failed to setup DUT instance:\n"
- f"{str(ex)}\n{traceback.format_exc()}")
- cls.__setup_disks()
-
- TestRun.LOGGER.info(f"Re-seeding random number generator with seed: {cls.random_seed}")
- random.seed(cls.random_seed)
-
- cls.plugin_manager.hook_post_setup()
-
-
-TestRun.setup = __setup
-
-
-@classmethod
-def __makereport(cls, item, call, res):
- cls.outcome = res.outcome
- step_info = {
- 'result': res.outcome,
- 'exception': str(call.excinfo.value) if call.excinfo else None
- }
- setattr(item, "rep_" + res.when, step_info)
-
- from _pytest.outcomes import Failed
- from core.test_run import Blocked
- if res.when == "call" and res.failed:
- msg = f"{call.excinfo.type.__name__}: {call.excinfo.value}"
- if call.excinfo.type is Failed:
- cls.LOGGER.error(msg)
- elif call.excinfo.type is Blocked:
- cls.LOGGER.blocked(msg)
- else:
- cls.LOGGER.exception(msg)
- elif res.when == "setup" and res.failed:
- msg = f"{call.excinfo.type.__name__}: {call.excinfo.value}"
- cls.LOGGER.exception(msg)
- res.outcome = "failed"
-
- if res.outcome == "skipped":
- cls.LOGGER.skip("Test skipped.")
-
- if res.when == "call" and cls.LOGGER.get_result() == BaseLogResult.FAILED:
- res.outcome = "failed"
- # To print additional message in final test report, assign it to res.longrepr
-
- cls.LOGGER.generate_summary(item, cls.config.get('meta'))
-
-
-TestRun.makereport = __makereport
-
-
-@classmethod
-def __generate_tests(cls, metafunc):
- marks = getattr(metafunc.function, "pytestmark", [])
-
- parametrizex_marks = [
- mark for mark in marks if mark.name == "parametrizex"
- ]
-
- if not parametrizex_marks:
- random.seed(TestRun.random_seed)
- return
-
- argnames = []
- argvals = []
- for mark in parametrizex_marks:
- argnames.append(mark.args[0])
- argvals.append(list(mark.args[1]))
-
- if metafunc.config.getoption("--parametrization-type") == "full":
- for name, values in zip(argnames, argvals):
- metafunc.parametrize(name, values)
- elif metafunc.config.getoption("--parametrization-type") == "pair":
- test_cases = generate_pair_testing_testcases(*argvals)
-
- register_testcases(metafunc, argnames, test_cases)
- else:
- raise Exception("Not supported parametrization type")
-
- random.seed(TestRun.random_seed)
-
-
-TestRun.generate_tests = __generate_tests
-
-
-@classmethod
-def __addoption(cls, parser):
- parser.addoption("--parametrization-type", choices=["pair", "full"], default="pair")
- parser.addoption("--random-seed", type=int, default=None)
-
-
-TestRun.addoption = __addoption
-
-
-@classmethod
-def __teardown(cls):
- for dut in cls.duts:
- with cls.use_dut(dut):
- if cls.plugin_manager:
- cls.plugin_manager.hook_teardown()
-
-
-TestRun.teardown = __teardown
diff --git a/test/functional/test-framework/internal_plugins/__init__.py b/test/functional/test-framework/internal_plugins/__init__.py
deleted file mode 100644
index dce958c..0000000
--- a/test/functional/test-framework/internal_plugins/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/test/functional/test-framework/internal_plugins/example_plugin/__init__.py b/test/functional/test-framework/internal_plugins/example_plugin/__init__.py
deleted file mode 100644
index 4bdec67..0000000
--- a/test/functional/test-framework/internal_plugins/example_plugin/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-class ExamplePlugin:
- def __init__(self, params, config):
- self.params = params
- print(f"Example plugin initialized with params {self.params}")
-
- def pre_setup(self):
- print("Example plugin pre setup")
-
- def post_setup(self):
- print("Example plugin post setup")
-
- def teardown(self):
- print("Example plugin teardown")
-
-
-plugin_class = ExamplePlugin
diff --git a/test/functional/test-framework/internal_plugins/power_control_libvirt/__init__.py b/test/functional/test-framework/internal_plugins/power_control_libvirt/__init__.py
deleted file mode 100644
index ca2993e..0000000
--- a/test/functional/test-framework/internal_plugins/power_control_libvirt/__init__.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-from datetime import timedelta
-
-from connection.local_executor import LocalExecutor
-from connection.ssh_executor import SshExecutor
-from core.test_run import TestRun
-
-
-class PowerControlPlugin:
- def __init__(self, params, config):
- print("Power Control LibVirt Plugin initialization")
- try:
- self.ip = config['ip']
- self.user = config['user']
- except Exception:
- raise Exception("Missing fields in config! ('ip' and 'user' required)")
-
- def pre_setup(self):
- print("Power Control LibVirt Plugin pre setup")
- if self.config['connection_type'] == 'ssh':
- self.executor = SshExecutor(
- self.ip,
- self.user,
- self.config.get('port', 22)
- )
- else:
- self.executor = LocalExecutor()
-
- def post_setup(self):
- pass
-
- def teardown(self):
- pass
-
- def power_cycle(self):
- self.executor.run(f"virsh reset {self.config['domain']}")
- TestRun.executor.wait_for_connection_loss()
- timeout = TestRun.config.get('reboot_timeout')
- if timeout:
- TestRun.executor.wait_for_connection(timedelta(seconds=int(timeout)))
- else:
- TestRun.executor.wait_for_connection()
-
-
-plugin_class = PowerControlPlugin
diff --git a/test/functional/test-framework/internal_plugins/scsi_debug/__init__.py b/test/functional/test-framework/internal_plugins/scsi_debug/__init__.py
deleted file mode 100644
index 95f6563..0000000
--- a/test/functional/test-framework/internal_plugins/scsi_debug/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-from time import sleep
-
-from core.test_run_utils import TestRun
-from storage_devices.device import Device
-from test_utils import os_utils
-from test_utils.output import CmdException
-
-
-class ScsiDebug:
- def __init__(self, params, config):
- self.params = params
- self.module_name = "scsi_debug"
-
- def pre_setup(self):
- pass
-
- def post_setup(self):
- self.reload()
-
- def reload(self):
- self.teardown()
- sleep(1)
- load_output = os_utils.load_kernel_module(self.module_name, self.params)
- if load_output.exit_code != 0:
- raise CmdException(f"Failed to load {self.module_name} module", load_output)
- TestRun.LOGGER.info(f"{self.module_name} loaded successfully.")
- sleep(10)
- TestRun.scsi_debug_devices = Device.get_scsi_debug_devices()
-
- def teardown(self):
- if os_utils.is_kernel_module_loaded(self.module_name):
- os_utils.unload_kernel_module(self.module_name)
-
-
-plugin_class = ScsiDebug
diff --git a/test/functional/test-framework/internal_plugins/vdbench/__init__.py b/test/functional/test-framework/internal_plugins/vdbench/__init__.py
deleted file mode 100644
index d0f7f71..0000000
--- a/test/functional/test-framework/internal_plugins/vdbench/__init__.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import time
-import posixpath
-
-from datetime import timedelta
-from core.test_run import TestRun
-from test_tools import fs_utils
-
-
-class Vdbench:
- def __init__(self, params, config):
- print("VDBench plugin initialization")
- self.run_time = timedelta(seconds=60)
-
- try:
- self.working_dir = config["working_dir"]
- self.reinstall = config["reinstall"]
- self.source_dir = config["source_dir"]
- except Exception:
- raise Exception("Missing fields in config! ('working_dir', 'source_dir' and "
- "'reinstall' required)")
-
- self.result_dir = posixpath.join(self.working_dir, 'result.tod')
-
- def pre_setup(self):
- pass
-
- def post_setup(self):
- print("VDBench plugin post setup")
- if not self.reinstall and fs_utils.check_if_directory_exists(self.working_dir):
- return
-
- if fs_utils.check_if_directory_exists(self.working_dir):
- fs_utils.remove(self.working_dir, True, True)
-
- fs_utils.create_directory(self.working_dir)
- TestRun.LOGGER.info("Copying vdbench to working dir.")
- fs_utils.copy(posixpath.join(self.source_dir, "*"), self.working_dir,
- True, True)
- pass
-
- def teardown(self):
- pass
-
- def create_config(self, config, run_time: timedelta):
- self.run_time = run_time
- if config[-1] != ",":
- config += ","
- config += f"elapsed={int(run_time.total_seconds())}"
- TestRun.LOGGER.info(f"Vdbench config:\n{config}")
- fs_utils.write_file(posixpath.join(self.working_dir, "param.ini"), config)
-
- def run(self):
- cmd = f"{posixpath.join(self.working_dir, 'vdbench')} " \
- f"-f {posixpath.join(self.working_dir, 'param.ini')} " \
- f"-vr -o {self.result_dir}"
- full_cmd = f"screen -dmS vdbench {cmd}"
- TestRun.executor.run(full_cmd)
- start_time = time.time()
-
- timeout = self.run_time * 1.5
-
- while True:
- if not TestRun.executor.run(f"ps aux | grep '{cmd}' | grep -v grep").exit_code == 0:
- return self.analyze_log()
-
- if time.time() - start_time > timeout.total_seconds():
- TestRun.LOGGER.error("Vdbench timeout.")
- return False
- time.sleep(1)
-
- def analyze_log(self):
- output = TestRun.executor.run(
- f"ls -1td {self.result_dir[0:len(self.result_dir) - 3]}* | head -1")
- log_path = posixpath.join(output.stdout if output.exit_code == 0 else self.result_dir,
- "logfile.html")
-
- log_file = fs_utils.read_file(log_path)
-
- if "Vdbench execution completed successfully" in log_file:
- TestRun.LOGGER.info("Vdbench execution completed successfully.")
- return True
-
- if "Data Validation error" in log_file or "data_errors=1" in log_file:
- TestRun.LOGGER.error("Data corruption occurred!")
- elif "Heartbeat monitor:" in log_file:
- TestRun.LOGGER.error("Vdbench: heartbeat.")
- else:
- TestRun.LOGGER.error("Vdbench unknown result.")
- return False
-
-
-plugin_class = Vdbench
diff --git a/test/functional/test-framework/log/__init__.py b/test/functional/test-framework/log/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/log/base_log.py b/test/functional/test-framework/log/base_log.py
deleted file mode 100644
index 0f717a4..0000000
--- a/test/functional/test-framework/log/base_log.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from enum import Enum
-from re import sub
-
-
-class BaseLogResult(Enum):
- DEBUG = 10
- PASSED = 11
- WORKAROUND = 12
- WARNING = 13
- SKIPPED = 14
- FAILED = 15
- EXCEPTION = 16
- BLOCKED = 17
- CRITICAL = 18
-
-
-def escape(msg):
- return sub(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', '', msg)
-
-
-class BaseLog():
- def __init__(self, begin_message=None):
- self.__begin_msg = begin_message
- self.__result = BaseLogResult.PASSED
-
- def __enter__(self):
- if self.__begin_msg is not None:
- self.begin(self.__begin_msg)
- else:
- self.begin("Start BaseLog ...")
-
- def __exit__(self, *args):
- self.end()
-
- def __try_to_set_new_result(self, new_result):
- if new_result.value > self.__result.value:
- self.__result = new_result
-
- def begin(self, message):
- pass
-
- def debug(self, message):
- pass
-
- def info(self, message):
- pass
-
- def workaround(self, message):
- self.__try_to_set_new_result(BaseLogResult.WORKAROUND)
-
- def warning(self, message):
- self.__try_to_set_new_result(BaseLogResult.WARNING)
-
- def skip(self, message):
- self.__try_to_set_new_result(BaseLogResult.SKIPPED)
-
- def error(self, message):
- self.__try_to_set_new_result(BaseLogResult.FAILED)
-
- def blocked(self, message):
- self.__try_to_set_new_result(BaseLogResult.BLOCKED)
-
- def exception(self, message):
- self.__try_to_set_new_result(BaseLogResult.EXCEPTION)
-
- def critical(self, message):
- self.__try_to_set_new_result(BaseLogResult.CRITICAL)
-
- def end(self):
- return self.__result
-
- def get_result(self):
- return self.__result
diff --git a/test/functional/test-framework/log/group/__init__.py b/test/functional/test-framework/log/group/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/log/group/html_chapter_group_log.py b/test/functional/test-framework/log/group/html_chapter_group_log.py
deleted file mode 100644
index 56fc7ca..0000000
--- a/test/functional/test-framework/log/group/html_chapter_group_log.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.base_log import BaseLogResult, BaseLog
-from log.group.html_group_log import HtmlGroupLog
-from datetime import datetime
-
-
-class HtmlChapterGroupLog(HtmlGroupLog):
- SET_RESULT = {
- BaseLogResult.PASSED: BaseLog.info,
- BaseLogResult.WORKAROUND: BaseLog.workaround,
- BaseLogResult.WARNING: BaseLog.warning,
- BaseLogResult.SKIPPED: BaseLog.skip,
- BaseLogResult.FAILED: BaseLog.error,
- BaseLogResult.BLOCKED: BaseLog.blocked,
- BaseLogResult.EXCEPTION: BaseLog.exception,
- BaseLogResult.CRITICAL: BaseLog.critical}
-
- def __init__(self, html_base, cfg, begin_msg=None, id='ch0'):
- super().__init__(HtmlChapterGroupLog._factory, html_base, cfg, begin_msg, id)
-
- @staticmethod
- def _factory(html_base, cfg, begin_msg, id):
- return HtmlChapterGroupLog(html_base, cfg, begin_msg, id)
-
- def end_dir_group(self, ref_group):
- group = super().end_group()
- ref_container_id = ref_group._container.get('id')
- group._header.set('ondblclick', f"chapterClick('{ref_container_id}')")
-
- def set_result(self, result):
- if self._successor is not None:
- self._successor.set_result(result)
- HtmlChapterGroupLog.SET_RESULT[result](self, "set result")
-
- def end(self):
- result = super().end()
- exe_time = (datetime.now() - self._start_time).seconds
- self._cfg.group_chapter_end(exe_time, self._header, self._container, result)
- return result
diff --git a/test/functional/test-framework/log/group/html_group_log.py b/test/functional/test-framework/log/group/html_group_log.py
deleted file mode 100644
index cba5075..0000000
--- a/test/functional/test-framework/log/group/html_group_log.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from datetime import datetime
-from log.base_log import BaseLog, BaseLogResult
-
-
-class HtmlGroupLog(BaseLog):
- def __init__(self, constructor, html_base_element, cfg, begin_message, id_):
- super().__init__(begin_message)
- self._successor = None
- self.__factory = constructor
- self.__log_main_store = html_base_element
- self._id = id_
- self._container = None
- self._header = None
- self.__msg_idx = 0
- self._start_time = datetime.now()
- self._cfg = cfg
- self._header_msg_type = type(begin_message)
-
- def begin(self, message):
- policy = self._cfg.get_policy(type(message))
- self._header, self._container = policy.group_begin(self._id, message, self.__log_main_store)
- super().begin(message)
-
- def get_step_id(self):
- if self._successor is not None:
- return self._successor.get_step_id()
- else:
- return f'step.{self._id}.{self.__msg_idx}'
-
- def __add_test_step(self, message, result=BaseLogResult.PASSED):
- policy = self._cfg.get_policy(type(message))
- policy.standard(self.get_step_id(), message, result, self._container)
- self.__msg_idx += 1
-
- def get_main_log_store(self):
- return self.__log_main_store
-
- def start_group(self, message):
- self._header_msg_type = type(message)
- if self._successor is not None:
- result = self._successor.start_group(message)
- else:
- new_id = f"{self._id}.{self.__msg_idx}"
- self.__msg_idx += 1
- self._successor = self.__factory(self._container, self._cfg, message, new_id)
- self._successor.begin(message)
- result = self._successor
- return result
-
- def end_group(self):
- if self._successor is not None:
- if self._successor._successor is None:
- self._successor.end()
- result = self._successor
- self._successor = None
- else:
- result = self._successor.end_group()
- else:
- self.end()
- result = self
- return result
-
- def debug(self, message):
- if self._successor is not None:
- self._successor.debug(message)
- else:
- self.__add_test_step(message, BaseLogResult.DEBUG)
- return super().debug(message)
-
- def info(self, message):
- if self._successor is not None:
- self._successor.info(message)
- else:
- self.__add_test_step(message)
- super().info(message)
-
- def workaround(self, message):
- if self._successor is not None:
- self._successor.workaround(message)
- else:
- self.__add_test_step(message, BaseLogResult.WORKAROUND)
- super().workaround(message)
-
- def warning(self, message):
- if self._successor is not None:
- self._successor.warning(message)
- else:
- self.__add_test_step(message, BaseLogResult.WARNING)
- super().warning(message)
-
- def skip(self, message):
- if self._successor is not None:
- self._successor.skip(message)
- else:
- self.__add_test_step(message, BaseLogResult.SKIPPED)
- super().skip(message)
-
- def error(self, message):
- if self._successor is not None:
- self._successor.error(message)
- else:
- self.__add_test_step(message, BaseLogResult.FAILED)
- super().error(message)
-
- def blocked(self, message):
- if self._successor is not None:
- self._successor.blocked(message)
- else:
- self.__add_test_step(message, BaseLogResult.BLOCKED)
- super().blocked(message)
-
- def critical(self, message):
- if self._successor is not None:
- self._successor.critical(message)
- else:
- self.__add_test_step(message, BaseLogResult.CRITICAL)
- super().critical(message)
-
- def exception(self, message):
- if self._successor is not None:
- self._successor.exception(message)
- else:
- self.__add_test_step(message, BaseLogResult.EXCEPTION)
- super().exception(message)
-
- def end(self):
- return super().end()
-
- def get_current_group(self):
- if self._successor is not None:
- result = self._successor.get_current_group()
- else:
- result = self
- return result
diff --git a/test/functional/test-framework/log/group/html_iteration_group_log.py b/test/functional/test-framework/log/group/html_iteration_group_log.py
deleted file mode 100644
index d594018..0000000
--- a/test/functional/test-framework/log/group/html_iteration_group_log.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.group.html_group_log import HtmlGroupLog
-
-
-class HtmlIterationGroupLog(HtmlGroupLog):
- def __init__(self, html_base, cfg, begin_msg, id='itg0'):
- super().__init__(HtmlIterationGroupLog._factory, html_base, cfg, begin_msg, id)
-
- @staticmethod
- def _factory(html_base, cfg, begin_msg, id):
- return HtmlIterationGroupLog(html_base, cfg, begin_msg, id)
-
- def end(self):
- result = super().end()
- self._cfg.group_end(self._id, self._header, self._container, result)
- return result
diff --git a/test/functional/test-framework/log/html_file_item_log.py b/test/functional/test-framework/log/html_file_item_log.py
deleted file mode 100644
index b529762..0000000
--- a/test/functional/test-framework/log/html_file_item_log.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.html_file_log import HtmlFileLog
-from log.group.html_chapter_group_log import HtmlChapterGroupLog
-from log.group.html_iteration_group_log import HtmlIterationGroupLog
-from datetime import datetime
-from lxml.etree import Element
-
-
-class HtmlFileItemLog(HtmlFileLog):
- def __init__(self, html_file_path, test_title, cfg, iteration_title="Test summary"):
- super().__init__(html_file_path, test_title)
- root = self.get_root()
- self._log_items_store = root.xpath('/html/body')[0]
- self._idx = 0
- self._log_chapters_store = root.xpath('/html/body/section[@id="iteration-chapters"]')[0]
- self._chapter_group = HtmlChapterGroupLog(self._log_chapters_store, cfg, test_title)
- self._main_group = HtmlIterationGroupLog(self._log_items_store, cfg, test_title)
- self._start_time = datetime.now()
- iteration_title_node = root.xpath('/html/body/a/h1')[0]
- iteration_title_node.text = iteration_title
- self._config = cfg
- self._fail_container = root.xpath('/html/body/div/select[@id="error-list-selector"]')[0]
-
- def __add_error(self, msg_idx, msg, error_class):
- fail_element = Element('option', value=msg_idx)
- fail_element.set('class', error_class)
- fail_element.text = msg
- self._fail_container.append(fail_element)
-
- def start_iteration(self, message):
- super().begin(message)
-
- def get_result(self):
- return self._main_group.get_result()
-
- def begin(self, message):
- self._chapter_group.begin(message)
- self._main_group.begin(message)
-
- def debug(self, message):
- self._main_group.debug(message)
-
- def info(self, message):
- self._main_group.info(message)
-
- def workaround(self, message):
- self._main_group.workaround(message)
-
- def warning(self, message):
- self._main_group.warning(message)
-
- def skip(self, message):
- self._main_group.skip(message)
-
- def error(self, message):
- msg_idx = self._main_group.get_step_id()
- self.__add_error(msg_idx, message, "fail")
- self._main_group.error(message)
-
- def blocked(self, message):
- msg_idx = self._main_group.get_step_id()
- self.__add_error(msg_idx, message, "blocked")
- self._main_group.blocked(message)
-
- def exception(self, message):
- msg_idx = self._main_group.get_step_id()
- self.__add_error(msg_idx, message, "exception")
- self._main_group.exception(message)
-
- def critical(self, message):
- msg_idx = self._main_group.get_step_id()
- self.__add_error(msg_idx, message, "critical")
- self._main_group.critical(message)
-
- def start_group(self, message):
- self._chapter_group.start_group(message)
- self._main_group.start_group(message)
-
- def end_group(self):
- ref_group = self._main_group.get_current_group()
- self._chapter_group.set_result(ref_group.get_result())
- self._main_group.end_group()
- self._chapter_group.end_dir_group(ref_group)
-
- def end_all_groups(self):
- while self._main_group._successor is not None:
- self.end_group()
-
- def end(self):
- while self._main_group._successor is not None:
- self.end_group()
- self.end_group()
- time_result = datetime.now() - self._start_time
- time_node = self.get_root().xpath('/html/body/div[@class="iteration-execution-time"]')[0]
- status_node = self.get_root().xpath('/html/body/div[@class="iteration-status"]')[0]
- self._config.end_iteration_func(
- time_node, status_node, time_result.total_seconds(), self.get_result())
- super().end()
diff --git a/test/functional/test-framework/log/html_file_log.py b/test/functional/test-framework/log/html_file_log.py
deleted file mode 100644
index 55680da..0000000
--- a/test/functional/test-framework/log/html_file_log.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.base_log import BaseLog
-from lxml.html import fromstring
-from lxml.html import tostring
-
-
-class HtmlFileLog(BaseLog):
- def __init__(self, file_path, title):
- super().__init__(title)
- self.__path = file_path
- with open(file_path) as file_stream:
- self.__root = fromstring(file_stream.read())
- node_list = self.__root.xpath('/html/head/title')
- node_list[0].text = title
-
- def get_path(self):
- return self.__path
-
- def get_root(self):
- return self.__root
-
- def end(self):
- with open(self.__path, "wb") as file:
- x = tostring(self.__root)
- file.write(x)
diff --git a/test/functional/test-framework/log/html_iteration_log.py b/test/functional/test-framework/log/html_iteration_log.py
deleted file mode 100644
index b4f6c4c..0000000
--- a/test/functional/test-framework/log/html_iteration_log.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.html_file_item_log import HtmlFileItemLog
-
-
-class HtmlIterationLog(HtmlFileItemLog):
- def __init__(self, test_title, iteration_title, config):
- self.iteration_closed: bool = False
- html_file = config.create_iteration_file()
- super().__init__(html_file, test_title, config, iteration_title)
diff --git a/test/functional/test-framework/log/html_log_config.py b/test/functional/test-framework/log/html_log_config.py
deleted file mode 100644
index d06e7f0..0000000
--- a/test/functional/test-framework/log/html_log_config.py
+++ /dev/null
@@ -1,204 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import os
-from os import path, environ, makedirs
-from datetime import datetime
-from shutil import copyfile
-from lxml.etree import Element
-from log.base_log import BaseLogResult
-from log.presentation_policy import null_policy
-
-
-def convert_seconds_to_str(time_in_sec):
- h = str(int(time_in_sec / 3600) % 24).zfill(2)
- m = str(int(time_in_sec / 60) % 60).zfill(2)
- s = str(int(time_in_sec % 60)).zfill(2)
- time_msg = f"{h}:{m}:{s} [s]"
- if time_in_sec > 86400:
- time_msg = f"{int(time_in_sec // (3600 * 24))}d {time_msg}"
- return time_msg
-
-
-class HtmlLogConfig:
- STYLE = {
- BaseLogResult.DEBUG: 'debug',
- BaseLogResult.PASSED: '',
- BaseLogResult.WORKAROUND: 'workaround',
- BaseLogResult.WARNING: 'warning',
- BaseLogResult.SKIPPED: 'skip',
- BaseLogResult.FAILED: 'fail',
- BaseLogResult.BLOCKED: 'blocked',
- BaseLogResult.CRITICAL: 'critical',
- BaseLogResult.EXCEPTION: 'exception'}
-
- __MAIN = 'main'
- __SETUP = 'setup'
- __T_ITERATION = 'iteration'
- __FRAMEWORK_T_FOLDER = 'template'
-
- MAIN = __MAIN + '.html'
- CSS = __MAIN + '.css'
- JS = __MAIN + '.js'
-
- ITERATION_FOLDER = 'iterations'
- SETUP = __SETUP + ".html"
-
- def iteration(self):
- return f'{HtmlLogConfig.__T_ITERATION}_{str(self._iteration_id).zfill(3)}.html'
-
- def __init__(self, base_dir=None, presentation_policy=null_policy):
- self._log_base_dir = base_dir
- if base_dir is None:
- if os.name == 'nt':
- self._log_base_dir = 'c:\\History'
- else:
- if environ["USER"] == 'root':
- self._log_base_dir = '/root/history'
- else:
- self._log_base_dir = f'/home/{environ["USER"]}'
- self._log_dir = None
- self._presentation_policy = {}
- self.register_presentation_policy(str, presentation_policy)
- self._iteration_id = 0
-
- def get_iteration_id(self):
- return self._iteration_id
-
- def get_policy(self, type):
- return self._presentation_policy[type]
-
- def get_policy_collection(self):
- for type, policy in self._presentation_policy.items():
- yield policy
-
- def register_presentation_policy(self, type, presentation_policy):
- self._presentation_policy[type] = presentation_policy
-
- def __find_template_file(self, name, relative_path=None):
- base_dir = path.dirname(path.abspath(__file__))
- file_path = path.join(base_dir, HtmlLogConfig.__FRAMEWORK_T_FOLDER)
- if relative_path is not None:
- file_path = path.join(file_path, relative_path)
- file_path = path.join(file_path, name)
- if path.isfile(file_path):
- return file_path
- else:
- raise Exception(
- f"Unable to find file: {name} in location: {os.path.dirname(file_path)}")
-
- def __get_main_template_file_path(self):
- return self.__find_template_file(HtmlLogConfig.MAIN)
-
- def _get_setup_template_file_path(self):
- return self.__find_template_file(HtmlLogConfig.SETUP, HtmlLogConfig.ITERATION_FOLDER)
-
- def __get_iteration_template_path(self):
- return self.__find_template_file(HtmlLogConfig.__T_ITERATION + '.html',
- HtmlLogConfig.ITERATION_FOLDER)
-
- def create_html_test_log(self, test_title):
- now = datetime.now()
- time_stamp = f"{now.year}_{str(now.month).zfill(2)}_{str(now.day).zfill(2)}_" \
- f"{str(now.hour).zfill(2)}_{str(now.minute).zfill(2)}_{str(now.second).zfill(2)}"
- self._log_dir = path.join(self._log_base_dir, test_title, time_stamp)
- makedirs(self._log_dir)
- additional_location = path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER)
- makedirs(additional_location)
- dut_info_folder = path.join(self._log_dir, 'dut_info')
- makedirs(dut_info_folder)
- main_html = self.__get_main_template_file_path()
- main_css = main_html.replace('html', 'css')
- main_js = main_html.replace('html', 'js')
- copyfile(main_html, path.join(self._log_dir, HtmlLogConfig.MAIN))
- copyfile(main_css, path.join(self._log_dir, HtmlLogConfig.CSS))
- copyfile(main_js, path.join(self._log_dir, HtmlLogConfig.JS))
- copyfile(self._get_setup_template_file_path(), path.join(additional_location,
- HtmlLogConfig.SETUP))
- return self._log_dir
-
- def get_main_file_path(self):
- return path.join(self._log_dir, HtmlLogConfig.MAIN)
-
- def get_setup_file_path(self):
- return path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER, HtmlLogConfig.SETUP)
-
- def create_iteration_file(self):
- self._iteration_id += 1
- template_file = self.__get_iteration_template_path()
- new_file_name = self.iteration()
- result = path.join(self._log_dir, HtmlLogConfig.ITERATION_FOLDER, new_file_name)
- copyfile(template_file, result)
- return result
-
- def end_iteration(self,
- iteration_selector_div,
- iteration_selector_select,
- iteration_id,
- iteration_result):
- style = "iteration-selector"
- if iteration_result != BaseLogResult.PASSED:
- style = f'{style} {HtmlLogConfig.STYLE[iteration_result]}'
- if iteration_id and iteration_id % 8 == 0:
- new_element = Element("br")
- iteration_selector_div[0].append(new_element)
- new_element = Element("a")
- new_element.set('class', style)
- new_element.set('onclick', f"selectIteration('{iteration_id}')")
- new_element.text = str(iteration_id)
- iteration_selector_div[0].append(new_element)
- new_element = Element('option', value=f"{iteration_id}")
- new_element.text = 'iteration_' + str(iteration_id).zfill(3)
- if iteration_result != BaseLogResult.PASSED:
- new_element.set('class', HtmlLogConfig.STYLE[iteration_result])
- iteration_selector_select.append(new_element)
-
- def end_setup_iteration(self, iteration_selector_div, iteration_selector_select, log_result):
- if log_result != BaseLogResult.PASSED:
- a_element = iteration_selector_div[0]
- select_element = iteration_selector_select[0]
- a_element.set('class', f'iteration-selector {HtmlLogConfig.STYLE[log_result]}')
- select_element.set('class', HtmlLogConfig.STYLE[log_result])
-
- def end_iteration_func(self, time_node, status_node, time_in_sec, log_result):
- time_node.text = f"Execution time: {convert_seconds_to_str(time_in_sec)}"
- status_node.text = f"Iteration status: {log_result.name}"
- if log_result != BaseLogResult.PASSED:
- status_node.set('class', f'iteration-status {HtmlLogConfig.STYLE[log_result]}')
-
- def end_main_log(self, test_status_div, log_result):
- if log_result != BaseLogResult.PASSED:
- test_status_div[0].set('class',
- f"sidebar-test-status {HtmlLogConfig.STYLE[log_result]}")
- test_status_div[0].text = f"Test status: {log_result.name}"
-
- def group_end(self, msg_id, html_header, html_container, log_result):
- html_header.set('onclick', f"showHide('ul_{msg_id}')")
- sub_element = Element('a', href="#top")
- sub_element.text = "[TOP]"
- sub_element.set('class', "top-time-marker")
- html_header.append(sub_element)
- div_style = 'test-group-step'
- ul_style = 'iteration-content'
- if log_result == BaseLogResult.PASSED:
- html_container.set('style', "display: none;")
- else:
- div_style = f"{div_style} {HtmlLogConfig.STYLE[log_result]}"
- ul_style = f"{ul_style} {HtmlLogConfig.STYLE[log_result]}"
- html_header.set('class', div_style)
- html_container.set('class', ul_style)
-
- def group_chapter_end(self, time_in_sec, html_header, html_container, log_result):
- sub_element = Element('a')
- sub_element.text = convert_seconds_to_str(time_in_sec)
- sub_element.set('class', 'top-marker')
- html_header.append(sub_element)
- div_style = 'test-group-step'
- ul_style = 'iteration-content'
- if log_result != BaseLogResult.PASSED:
- div_style = f"{div_style} {HtmlLogConfig.STYLE[log_result]}"
- ul_style = f"{ul_style} {HtmlLogConfig.STYLE[log_result]}"
- html_header.set('class', div_style)
- html_container.set('class', ul_style)
diff --git a/test/functional/test-framework/log/html_log_manager.py b/test/functional/test-framework/log/html_log_manager.py
deleted file mode 100644
index 30ba196..0000000
--- a/test/functional/test-framework/log/html_log_manager.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-from log.base_log import BaseLog, escape
-from log.html_iteration_log import HtmlIterationLog
-from log.html_log_config import HtmlLogConfig
-from log.html_main_log import HtmlMainLog
-from log.html_setup_log import HtmlSetupLog
-
-
-class HtmlLogManager(BaseLog):
- def __init__(self, begin_message=None, log_config=None):
- super().__init__(begin_message)
- self._config = HtmlLogConfig() if log_config is None else log_config
- self._main = None
- self._log_setup = None
- self._log_iterations = []
- self._current_log = None
- self._files_path = None
-
- def __add(self, msg):
- pass
-
- def begin(self, message):
- self._files_path = self._config.create_html_test_log(message)
- self._main = HtmlMainLog(message, self._config)
- self._log_setup = HtmlSetupLog(message, config=self._config)
- self._current_log = self._log_setup
- self._main.begin(message)
- self._current_log.begin(message)
- self.__add("begin: " + message)
-
- @property
- def base_dir(self):
- return self._files_path
-
- def get_result(self):
- log_result = self._log_setup.get_result()
- for iteration in self._log_iterations:
- if log_result.value < iteration.get_result().value:
- log_result = iteration.get_result()
- return log_result
-
- def end(self):
- self._log_setup.end()
- self._main.end_setup_iteration(self._log_setup.get_result())
- log_result = self.get_result()
- self._main.end(log_result)
- self.__add("end")
-
- def add_build_info(self, message):
- self._main.add_build_info(escape(message))
-
- def start_iteration(self, message):
- message = escape(message)
- self._log_iterations.append(HtmlIterationLog(message, message, self._config))
- self._main.start_iteration(self._config.get_iteration_id())
- self._current_log = self._log_iterations[-1]
- self._current_log.begin(message)
- self._log_setup.start_iteration(message)
- self.__add("start_iteration: " + message)
-
- def end_iteration(self):
- self._current_log.end()
- self._main.end_iteration(self._current_log.get_result())
- self._log_setup.end_iteration(self._current_log.get_result())
- self._current_log.iteration_closed = True
- self._current_log = self._log_setup
- self.__add("end_iteration: ")
- return self._current_log
-
- def debug(self, message):
- self._current_log.debug(escape(message))
- self.__add("debug: " + message)
-
- def info(self, message):
- self._current_log.info(escape(message))
- self.__add("info: " + message)
-
- def workaround(self, message):
- self._current_log.workaround(escape(message))
- self.__add(": " + message)
-
- def warning(self, message):
- self._current_log.warning(escape(message))
- self.__add(": " + message)
-
- def skip(self, message):
- self._current_log.skip(escape(message))
- self.__add("warning: " + message)
-
- def error(self, message):
- self._current_log.error(escape(message))
- self.__add("error: " + message)
-
- def blocked(self, message):
- self._current_log.blocked(escape(message))
- self.__add(f'blocked: {message}')
- self.end_all_groups()
-
- def exception(self, message):
- self._current_log.exception(escape(message))
- self.__add("exception: " + message)
- self.end_all_groups()
-
- def critical(self, message):
- self._current_log.critical(escape(message))
- self.__add("critical: " + message)
- self.end_all_groups()
-
- def start_group(self, message):
- self._current_log.start_group(escape(message))
- self.__add("start_group: " + message)
-
- def end_group(self):
- self._current_log.end_group()
- self.__add("end_group")
-
- def end_all_groups(self):
- for iteration in reversed(self._log_iterations):
- if not iteration.iteration_closed:
- self.end_iteration()
- self._current_log.end_all_groups()
diff --git a/test/functional/test-framework/log/html_main_log.py b/test/functional/test-framework/log/html_main_log.py
deleted file mode 100644
index f19f070..0000000
--- a/test/functional/test-framework/log/html_main_log.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.html_file_log import HtmlFileLog
-from lxml.etree import Element
-
-
-class HtmlMainLog(HtmlFileLog):
- def __init__(self, title, config):
- super().__init__(config.get_main_file_path(), title)
- self._config = config
- self.__current_iteration_id = None
- root = self.get_root()
- test_title_div = root.xpath('/html/body/div/div/div/div[@class="sidebar-test-title"]')[0]
- test_title_div.text = title
- self.__build_information_set = root.xpath(
- '/html/body/div/div/div/div[@id="sidebar-tested-build"]')[0]
-
- def add_build_info(self, message):
- build_info = Element("div")
- build_info.text = message
- self.__build_information_set.append(build_info)
-
- def start_iteration(self, iteration_id):
- self.__current_iteration_id = iteration_id
-
- def end_iteration(self):
- pass
-
- def end_iteration(self, iteration_result):
- root = self.get_root()
- iteration_selector_div = root.xpath('/html/body/div/div/div[@id="iteration-selector"]')
- iteration_selector_select = root.xpath(
- '/html/body/div/div/select[@id="sidebar-iteration-list"]')[0]
- self._config.end_iteration(iteration_selector_div,
- iteration_selector_select,
- self.__current_iteration_id,
- iteration_result)
-
- def end_setup_iteration(self, result):
- root = self.get_root()
- iteration_selector_div = root.xpath('/html/body/div/div/div[@id="iteration-selector"]')[0]
- iteration_selector_select = root.xpath(
- '/html/body/div/div/select[@id="sidebar-iteration-list"]')[0]
- self._config.end_setup_iteration(iteration_selector_div, iteration_selector_select, result)
-
- def end(self, result):
- root = self.get_root()
- test_status_div = root.xpath('/html/body/div/div/div/div[@class="sidebar-test-status"]')
- self._config.end_main_log(test_status_div, result)
- super().end()
diff --git a/test/functional/test-framework/log/html_presentation_policy.py b/test/functional/test-framework/log/html_presentation_policy.py
deleted file mode 100644
index 62cb7be..0000000
--- a/test/functional/test-framework/log/html_presentation_policy.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.base_log import BaseLogResult
-from lxml.etree import Element
-from datetime import datetime
-from log.presentation_policy import PresentationPolicy
-from log.html_log_config import HtmlLogConfig
-
-
-def std_log_entry(msg_id, msg, log_result, html_node):
- test_step = Element('li')
- style = 'test-step'
- if log_result != BaseLogResult.PASSED:
- style = f"{style} {HtmlLogConfig.STYLE[log_result]}"
- test_step.set('class', style)
- test_time = Element('div')
- test_time.set('class', 'ts-time')
- test_time_txt = Element('a', name=msg_id)
- time = datetime.now()
- test_time_txt.text = f"{str(time.hour).zfill(2)}:" \
- f"{str(time.minute).zfill(2)}:{str(time.second).zfill(2)}"
- test_time.append(test_time_txt)
- test_step.append(test_time)
- test_msg = Element('div')
- test_msg.set('class', 'ts-msg')
- test_msg.text = msg
- test_step.append(test_msg)
- html_node.append(test_step)
-
-
-def group_log_begin(msg_id, msg, html_node):
- element = Element("div")
- sub_element = Element('a', name=msg_id)
- sub_element.text = msg
- element.append(sub_element)
- html_node.append(element)
- ul_set = Element('ul', id=f'ul_{msg_id}')
- html_node.append(ul_set)
- return element, ul_set
-
-
-html_policy = PresentationPolicy(std_log_entry, group_log_begin)
diff --git a/test/functional/test-framework/log/html_setup_log.py b/test/functional/test-framework/log/html_setup_log.py
deleted file mode 100644
index 3b93fb3..0000000
--- a/test/functional/test-framework/log/html_setup_log.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from log.html_file_item_log import HtmlFileItemLog
-from log.base_log import BaseLogResult
-
-
-class HtmlSetupLog(HtmlFileItemLog):
-
- LOG_RESULT = {
- BaseLogResult.PASSED: HtmlFileItemLog.info,
- BaseLogResult.WORKAROUND: HtmlFileItemLog.workaround,
- BaseLogResult.WARNING: HtmlFileItemLog.warning,
- BaseLogResult.SKIPPED: HtmlFileItemLog.skip,
- BaseLogResult.FAILED: HtmlFileItemLog.error,
- BaseLogResult.BLOCKED: HtmlFileItemLog.blocked,
- BaseLogResult.EXCEPTION: HtmlFileItemLog.exception,
- BaseLogResult.CRITICAL: HtmlFileItemLog.critical}
-
- def __init__(self, test_title, config, iteration_title="Test summary"):
- html_file_path = config.get_setup_file_path()
- super().__init__(html_file_path, test_title, config, iteration_title)
- self._last_iteration_title = ''
-
- def start_iteration(self, message):
- self._last_iteration_title = message
-
- def end_iteration(self, iteration_result):
- HtmlSetupLog.LOG_RESULT[iteration_result](self, self._last_iteration_title)
-
- def end(self):
- super().end()
diff --git a/test/functional/test-framework/log/logger.py b/test/functional/test-framework/log/logger.py
deleted file mode 100644
index 07a40bb..0000000
--- a/test/functional/test-framework/log/logger.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import logging
-import os
-import sys
-from contextlib import contextmanager
-from datetime import datetime
-from threading import Lock
-
-import portalocker
-
-from log.html_log_config import HtmlLogConfig
-from log.html_log_manager import HtmlLogManager
-from log.html_presentation_policy import html_policy
-from test_utils.output import Output
-from test_utils.singleton import Singleton
-
-
-def create_log(log_base_path, test_module, additional_args=None):
- Log.setup()
- log_cfg = HtmlLogConfig(base_dir=log_base_path,
- presentation_policy=html_policy)
- log = Log(log_config=log_cfg)
- test_name = 'TestNameError'
- error_msg = None
- try:
- test_name = test_module
- if additional_args:
- test_name += f"__{'_'.join(additional_args)}"
- except Exception as ex:
- error_msg = f'Detected some problems during calculating test name: {ex}'
- finally:
- log.begin(test_name)
- print(f"\n{os.path.join(log.base_dir, 'main.html')}")
- if error_msg:
- log.exception(error_msg)
- return log
-
-
-class Log(HtmlLogManager, metaclass=Singleton):
- logger = None
- LOG_FORMAT = '%(asctime)s %(levelname)s:\t%(message)s'
- DATE_FORMAT = "%Y/%m/%d %H:%M:%S"
- command_id = 0
- lock = Lock()
-
- @classmethod
- def destroy(cls):
- del cls._instances[cls]
-
- @classmethod
- def setup(cls):
-
- # Get handle to root logger.
- logger = logging.getLogger()
- logger.setLevel(logging.DEBUG)
-
- # Set paramiko log level to warning
- logging.getLogger('paramiko').setLevel(logging.WARNING)
-
- # Create Handlers.
- stdout_handler = logging.StreamHandler(sys.stdout)
-
- # Set logging level on handlers.
- stdout_handler.setLevel(logging.DEBUG)
-
- # Set log formatting on each handler.
- formatter = logging.Formatter(Log.LOG_FORMAT, Log.DATE_FORMAT)
- stdout_handler.setFormatter(formatter)
-
- # Attach handlers to root logger.
- logger.handlers = []
- logger.addHandler(stdout_handler)
- cls.logger = logger
- logger.info("Logger successfully initialized.")
-
- @contextmanager
- def step(self, message):
- self.step_info(message)
- super(Log, self).start_group(message)
- if Log.logger:
- Log.logger.info(message)
- yield
- super(Log, self).end_group()
-
- @contextmanager
- def group(self, message):
- self.start_group(message)
- yield
- self.end_group()
-
- def add_build_info(self, msg):
- super(Log, self).add_build_info(msg)
- if Log.logger:
- Log.logger.info(msg)
-
- def info(self, msg):
- super(Log, self).info(msg)
- if Log.logger:
- Log.logger.info(msg)
-
- def debug(self, msg):
- super(Log, self).debug(msg)
- if Log.logger:
- Log.logger.debug(msg)
-
- def error(self, msg):
- super(Log, self).error(msg)
- if Log.logger:
- Log.logger.error(msg)
-
- def blocked(self, msg):
- super(Log, self).blocked(msg)
- if Log.logger:
- Log.logger.fatal(msg)
-
- def exception(self, msg):
- super(Log, self).exception(msg)
- if Log.logger:
- Log.logger.exception(msg)
-
- def critical(self, msg):
- super(Log, self).critical(msg)
- if Log.logger:
- Log.logger.fatal(msg)
-
- def workaround(self, msg):
- super(Log, self).workaround(msg)
- if Log.logger:
- Log.logger.warning(msg)
-
- def warning(self, msg):
- super(Log, self).warning(msg)
- if Log.logger:
- Log.logger.warning(msg)
-
- def get_new_command_id(self):
- self.lock.acquire()
- command_id = self.command_id
- self.command_id += 1
- self.lock.release()
- return command_id
-
- def write_to_command_log(self, message):
- super(Log, self).debug(message)
- command_log_path = os.path.join(self.base_dir, "dut_info", 'commands.log')
- timestamp = datetime.now().strftime('%Y-%m-%d_%H:%M:%S:%f')
- with portalocker.Lock(command_log_path, "ab+") as command_log:
- line_to_write = f"[{timestamp}] {message}\n"
- command_log.write(line_to_write.encode())
-
- def write_command_to_command_log(self, command, command_id, info=None):
- added_info = "" if info is None else f"[{info}] "
- self.write_to_command_log(f"{added_info}Command id: {command_id}\n{command}")
-
- def write_output_to_command_log(self, output: Output, command_id):
- if output is not None:
- line_to_write = f"Command id: {command_id}\n\texit code: {output.exit_code}\n" \
- f"\tstdout: {output.stdout}\n" \
- f"\tstderr: {output.stderr}\n\n\n"
- self.write_to_command_log(line_to_write)
- else:
- self.write_to_command_log(f"Command id: {command_id}\n\tNone output.")
-
- def step_info(self, step_name):
- from core.test_run import TestRun
- decorator = "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n\n"
- message = f"\n\n\n{decorator}{step_name}\n\n{decorator}\n"
-
- try:
- serial_monitor = TestRun.plugin_manager.get_plugin("serial_monitor")
- serial_monitor.send_to_serial(message)
- except (KeyError, AttributeError):
- pass
- self.write_to_command_log(message)
-
- def get_additional_logs(self):
- from core.test_run import TestRun
- from test_tools.fs_utils import check_if_file_exists
- messages_log = "/var/log/messages"
- if not check_if_file_exists(messages_log):
- messages_log = "/var/log/syslog"
- log_files = {"messages.log": messages_log,
- "dmesg.log": "/tmp/dmesg"}
- extra_logs = TestRun.config.get("extra_logs", {})
- log_files.update(extra_logs)
-
- TestRun.executor.run(f"dmesg > {log_files['dmesg.log']}")
-
- for log_name, log_source_path in log_files.items():
- try:
- log_destination_path = os.path.join(
- self.base_dir, f"dut_info", TestRun.dut.ip, log_name
- )
- TestRun.executor.rsync_from(log_source_path, log_destination_path)
- except Exception as e:
- TestRun.LOGGER.warning(
- f"There was a problem during gathering {log_name} log.\n{str(e)}"
- )
-
- def generate_summary(self, item, meta):
- import json
- summary_path = os.path.join(self.base_dir, 'info.json')
- with open(summary_path, "w+") as summary:
- data = {
- 'module': os.path.relpath(item.fspath, os.getcwd()),
- 'function': item.name,
- 'meta': meta,
- 'status': self.get_result().name,
- 'path': os.path.normpath(self.base_dir),
- 'stage_status': {
- 'setup': getattr(item, "rep_setup", {}),
- 'call': getattr(item, "rep_call", {}),
- 'teardown': getattr(item, "rep_teardown", {})
- }
- }
- json.dump(data, summary)
diff --git a/test/functional/test-framework/log/presentation_policy.py b/test/functional/test-framework/log/presentation_policy.py
deleted file mode 100644
index 5409d08..0000000
--- a/test/functional/test-framework/log/presentation_policy.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-class PresentationPolicy:
- def __init__(self, standard_log, group_begin_func):
- self.standard = standard_log
- self.group_begin = group_begin_func
-
-
-def std_log_entry(msg_id, msg, log_result, html_node):
- pass
-
-
-def group_log_begin(msg_id, msg, html_node):
- return html_node, html_node
-
-
-null_policy = PresentationPolicy(std_log_entry, group_log_begin)
diff --git a/test/functional/test-framework/log/template/iterations/iteration.html b/test/functional/test-framework/log/template/iterations/iteration.html
deleted file mode 100644
index 15a315e..0000000
--- a/test/functional/test-framework/log/template/iterations/iteration.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- [title]
-
-
-
-
-
-
- View:
-
- Errors:
-
-
-
-
-
- [title]
- Iteration status: [status]
- Execution time: [time] [s]
-
-
-
diff --git a/test/functional/test-framework/log/template/iterations/setup.html b/test/functional/test-framework/log/template/iterations/setup.html
deleted file mode 100644
index c59dd42..0000000
--- a/test/functional/test-framework/log/template/iterations/setup.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
- Setup
-
-
-
-
-
-
- View:
-
- Errors:
-
-
-
-
-
-
- Test summary
-
- Iteration status: [STATUS]
- Execution time: [time] [s]
-
-
-
diff --git a/test/functional/test-framework/log/template/main.css b/test/functional/test-framework/log/template/main.css
deleted file mode 100644
index 4f5449d..0000000
--- a/test/functional/test-framework/log/template/main.css
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- Copyright(c) 2019-2021 Intel Corporation
- SPDX-License-Identifier: BSD-3-Clause
-*/
-
-html, body {
- margin: 0;
- padding: 0;
- background-color: #F0F0F0;
- font-family: Calibri;
- color: black;
-}
-
-div { display: block; }
-
-h2 { margin: 0; padding: 0; }
-h4 { margin: 0; padding: 0; }
-
-div.meta-container {
- margin-left: 502px;
- min-width: 500px;
- height: 100vh;
-}
-
-div.main-layaut {
- float: right;
- width: 100%;
- background-color: #FDFDFD;
- height: 100vh;
- overflow-y: scroll;
- overflow-x: hidden;
-}
-
-div.sidebar {
- float: left;
- width: 500px;
- height: 100vh;
- margin-left: -502px;
- border: 4px;
- background-color: #F0F0F0;
- overflow-x: hidden;
- overflow-y: auto;
- text-align: center;
- color: white;
- overflow-x: hidden;
- overflow-y: hidden;
-}
-
-div.sidebar-hide {
- padding: 3px;
- height: 20px;
- margin: 5px auto;
- font-family: Consolas;
- font-weight: normal;
- font-size: 15px;
- color: white;
- text-shadow: 1px 1px 3px black;
- background-color: rgb(40,80,180);
- cursor: default;
- border: 2px solid silver;
- border-radius: 25px;
-}
-
-div.sidebar-show { color: balck; height: 50%; }
-
-div.sidebar-test { overflow-x: hidden; overflow-y: hidden;}
-
-div.sidebar-test-title {
- padding: 10px;
- height: 40px;
- margin: 5px auto;
- background-color: rgb(40,80,180);
- font-size: 100%;
- border: 2px solid silver;
- border-radius: 25px;
-}
-
-div.sidebar-test-status {
- padding: 3px;
- height: 20px;
- background-color: green;
- border: 2px solid silver;
- border-radius: 25px;
-}
-
-div.sidebar-tested-build {
- color: black;
- border-radius: 25px;
- width: 80%;
- margin: 5px auto;
- padding: 25px;
- background-color: #F7F7F7;
- border: 1px solid silver;
- word-wrap: break-word;
- word-break: break-all;
- overflow: hidden;
- text-align: left;
-}
-
-div.sidebar-test-iteration {
- padding: 3px;
- height: 20px;
- margin: 5px auto;
- font-family: Consolas;
- font-weight: normal;
- font-size: 15px;
- color: white;
- text-shadow: 1px 1px 3px black;
- background-color: rgb(40,80,180);
- cursor: default;
- border: 2px solid silver;
- border-radius: 25px;
-}
-
-.debug { display: none; }
-
-select.sidebar-iteration-list {
- margin: 5px auto;
- background-color: white;
- color: black;
- width: 90%;
-}
-select.warning { background-color: #ff0; color: black; }
-select.workaround { background-color: #fff8dc; color: black; }
-select.skip { background-color: silver; color: black; }
-select.fail { background-color: red; color: white; }
-select.blocked { background-color: #7030a0; color: white; }
-select.exception { background-color: #e29517; color: white; }
-select.critical { background-color: #002060; color: white; }
-
-option {
- background-color: green;
- color: white;
- margin: 2px;
-}
-option.warning { background-color: #ff0; color: black; }
-option.workaround { background-color: #fff8dc; color: black; }
-option.skip { background-color: silver; color: black; }
-option.error { background-color: red; color: white; }
-option.blocked { background-color: #7030a0; color: white; }
-option.exception { background-color: #e29517; color: white; }
-select.critical { background-color: #002060; color: white; }
-
-a.iteration-selector {
- border: 2px solid silver;
- border-radius: 40px;
- width: 36px;
- height: 36px;
- margin: 0;
- padding: 0;
- vertical-align: middle;
- display: table-cell;
- color: white;
- background-color: green;
- text-shadow: 0 0 3px black;
- font-size: 20px;
- font-weight: bold;
- line-height: 1em;
- text-align: center;
- cursor: pointer;
-}
-a.warning { background-color: #ff0; }
-a.workaround { background-color: #fff8dc; }
-a.skip { background-color: silver; }
-a.fail { background-color: red; }
-a.exception { background-color: #e29517; }
-a.blocked { background-color: #7030a0; }
-a.critical { background-color: #002060; }
-a.selected { border: 2px solid black; }
-
-select.error-list-selector { background-color: silver; }
-
-div.test-chapter-step {
- margin: 4px auto;
- border-style: solid;
- border-color: #8CB9AE;
- border-radius: 10px;
- padding-left: 10px;
- padding-right: 10px;
- cursor: pointer;
-}
-
-div.sidebar-copyright {
- position: absolute;
- background-color: #DDD;
- text-align: center;
- padding: 4px;
- color: #888;
- bottom: 0;
- font-size: 12px;
- font-family: Consolas;
-}
-
-div.floating {
- right: 0;
- border: 3px solid silver;
- width: 40%;
- text-align: center;
- vertical-align: top;
- position: fixed;
- background-color : #F0F0F0;
- border-bottom: 1px solid #999;
- z-index: 999;
- color: #333;
- box-shadow: 0 0px 6px gray;
-}
-
-h1 {
- display: block;
- font-size: 2em;
- font-weight: bold;
-}
-
-div.iteration-selector {
- margin: 5px auto;
-}
-
-div.iteration-status {
- padding: 3px;
- height: 20px;
- background-color: green;
- border: 2px solid silver;
- border-radius: 25px;
- color: white;
- text-align: center;
-}
-
-h1.iteration-title { text-align: center; }
-
-div.iteration-execution-time { text-align: center; }
-
-section.iteration-chapters {
- border-radius: 25px;
- width: 80%;
- margin: 10px auto;
- padding: 25px;
- background-color: #F7F7F7;
- border: 1px solid silver;
- word-wrap: break-word;
- word-break: break-all;
- overflow: hidden;
-}
-
-ul.iteration-content {
- list-style-type: none;
- border-left-color: green;
- border-left-style: solid;
- margin: 0px;
-}
-ul.warning { border-left-color: #ff0; }
-ul.workaround { border-left-color: #fff8dc; }
-ul.skip { border-left-color: silver; }
-ul.fail { border-left-color: red; }
-ul.blocked { border-left-color: #7030a0; }
-ul.critical { border-left-color: #002060; }
-ul.exception { border-left-color: #e29517; }
-
-li.iteration-content {
- border-color: rgba(192, 192, 192, 1);
- background-color: rgba(238, 238, 238, 1);
- display: block;
- margin: 2px auto;
- border: 1px solid #C0C0C0;
- padding: 3px 6px;
- font-family: Calibri;
- font-size: 16px;
- line-height: 1.15em;
- word-wrap: break-word;
- word-break: break-all;
- overflow: hidden;
- border-left-color: green;
- border-left-style: solid;
- word-break: break-all;
-}
-
-div.test-group-step {
- color: black;
- background-color: #8CB9AE;
- border: 1px solid #5C8880;
- font-size: 18px;
- letter-spacing: 2px;
- cursor: pointer;
- margin: 4px;
- border-radius: 10px;
- padding-left: 10px;
- padding-right: 10px;
- overflow-wrap: break-word;
- word-wrap: break-word;
- word-break: break-all;
-}
-
-div.warning { background-color: #ff0; color: black; }
-div.workaround { background-color: #fff8dc; color: black; }
-div.skip { background-color: silver; color: black; }
-div.fail { background-color: red; color: white; }
-div.blocked { background-color: #7030a0; color: white; }
-div.critical { background-color: #002060; color: white; }
-div.exception { background-color: #e29517; color: white; }
-
-a.top-marker { cursor: pointer; float: right; }
-
-a.top-time-marker {
- word-wrap: break-word;
- float: right;
-}
-
-li.test-step {
- color: black;
- border-color: rgba(192, 192, 192, 1);
- background-color: rgba(238, 238, 238, 1);
- display: block;
- margin: 4px auto;
- border: 1px solid #C0C0C0;
- padding: 3px 6px;
- font-family: Calibri;
- font-size: 16px;
- line-height: 1.15em;
- word-wrap: break-word;
- word-break: break-all;
- overflow: hidden;
- border-left-color: green;
- border-left-style: solid;
- border-radius: 10px;
- padding-left: 10px;
- padding-right: 10px
-}
-li.warning { background-color: #ff0; border-left-color: #ff0; }
-li.workaround { background-color: #fff8dc; border-left-color: #fff8dc; }
-li.skip { background-color: silver; border-left-color: silver; }
-li.fail {
- background-color: red;
- border-left-color: red;
- color: white;
-}
-li.blocked {
- background-color: #7030a0;
- border-left-color: #7030a0;
- color: white;
-}
-li.exception {
- background-color: #e29517;
- border-left-color: #e29517;
- color: white;
-}
-
-li.critical {
- background-color: #002060;
- border-left-color: #002060;
- color: white;
-}
-
-div.ts-iteration {
- float: left;
- margin: 2px auto;
- border: 1px solid silver;
- padding: 3px 3px;
- text-align: center;
-}
-
-div.ts-total-time {
- margin: 2px auto;
- border: 1px solid silver;
- padding: 3px 3px;
- text-align: right;
-}
-
-div.ts-time {
- float: left;
- font-size: 12px;
- margin: 2px auto;
- border: 1px solid #A7A7A7;
- padding: 3px 3px;
-}
-
-div.ts-msg {
- font-size: 16px;
- font-family: Courier;
- margin: 2px auto;
- border: 1px solid #A7A7A7;
- padding: 3px 3px;
- white-space: pre-wrap;
- word-break: break-all;
-}
diff --git a/test/functional/test-framework/log/template/main.html b/test/functional/test-framework/log/template/main.html
deleted file mode 100644
index 8d0da20..0000000
--- a/test/functional/test-framework/log/template/main.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- [test title]
-
-
-
-
-
-
-
-
diff --git a/test/functional/test-framework/log/template/main.js b/test/functional/test-framework/log/template/main.js
deleted file mode 100644
index 79e81d8..0000000
--- a/test/functional/test-framework/log/template/main.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- Copyright(c) 2019-2021 Intel Corporation
- SPDX-License-Identifier: BSD-3-Clause
-*/
-
-function onLoadDocument() {
- hideDebug();
-}
-
-function selectMode() {
- var selector = document.getElementById('mode-selector');
- if (selector.value.includes('info')) {
- hideDebug();
- } else {
- showDebug();
- }
-}
-
-function hideDebug() {
- var debugTestStepArray = document.getElementsByTagName('li');
- for (i = 0; i < debugTestStepArray.length; i ++) {
- if(debugTestStepArray[i].className.includes('debug')) {
- debugTestStepArray[i].style.display = 'none';
- }
- }
-}
-
-function showDebug() {
- var debugTestStepArray = document.getElementsByTagName('li');
- for (i = 0; i < debugTestStepArray.length; i ++) {
- if(debugTestStepArray[i].className.includes('debug')) {
- debugTestStepArray[i].style.display = '';
- }
- }
-}
-
-function sidebarCtrl(ctrlHideId, ctrlShowClass) {
- var metaContainer = document.getElementsByClassName("meta-container")[0];
- var sidebar = document.getElementsByClassName('sidebar')[0];
- var sidebarTest = document.getElementById('sidebar-test');
- var ctrlHide = document.getElementById(ctrlHideId);
- var ctrlShowSet = document.getElementsByClassName(ctrlShowClass);
-
- if(sidebar.style.width.includes('15px')) {
- showSidebar(metaContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest);
- } else {
- hideSidebar(metaContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest);
- }
-}
-
-function showSidebar(mContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest) {
- sidebar.style.cursor = 'default';
- mContainer.style.marginLeft = '';
- sidebarTest.style.width = '';
- sidebarTest.style.height = '';
- sidebar.style.height = '';
- sidebar.style.marginLeft = '';
- sidebar.style.width = '';
- var i;
- for (i = 0; i < sidebarTest.children.length; i++) {
- sidebarTest.children[i].style.display = '';
- }
- document.getElementById('iteration-selector').style.display = '';
- document.getElementById('sidebar-iteration-list').style.display = '';
- document.getElementById('sidebar-copyright').style.display = '';
- for(i = 0; i < ctrlShowSet.length; i ++) {
- ctrlShowSet[i].style.display = 'none';
- }
-}
-
-function hideSidebar(mContainer, sidebar, ctrlHide, ctrlShowSet, sidebarTest) {
- document.getElementById('iteration-selector').style.display = 'none';
- document.getElementById('sidebar-iteration-list').style.display = 'none';
- document.getElementById('sidebar-copyright').style.display = 'none';
- var i;
- for (i = 0; i < sidebarTest.children.length; i++) {
- sidebarTest.children[i].style.display = 'none';
- }
- sidebarTest.style.display = '';
- for(i = 0; i < ctrlShowSet.length; i ++) {
- ctrlShowSet[i].style.display = '';
- ctrlShowSet[i].style.color = 'black';
- }
- sidebar.style.width = '15px';
- sidebar.style.marginLeft = '-15px';
- sidebar.style.height = '100%';
- sidebarTest.style.height = '100%';
- sidebarTest.style.width = '100%';
- mContainer.style.marginLeft = '16px';
- sidebar.style.cursor = 'pointer';
-}
-
-function previousError() {
- var errorSelector = document.getElementById("error-list-selector");
- if (errorSelector.length > 1) {
- var id = errorSelector.selectedIndex;
- if (id - 1 > 0) {
- errorSelector.selectedIndex = (id - 1);
- } else {
- errorSelector.selectedIndex = (errorSelector.length - 1);
- }
- errorSelected('error-list-selector');
- }
-}
-
-function nextError() {
- var errorSelector = document.getElementById("error-list-selector");
- if (errorSelector.length > 1) {
- var id = errorSelector.selectedIndex;
- if (id + 1 < errorSelector.length) {
- errorSelector.selectedIndex = (id + 1);
- } else {
- errorSelector.selectedIndex = 1;
- }
- errorSelected('error-list-selector');
- }
-}
-
-function selectIterationFromSelect() {
- var element = document.getElementById("sidebar-iteration-list");
- loadDocument(element.value);
- updateIterationSelector(element);
-}
-
-function clickSelectIteration() {
- var element = document.getElementById("sidebar-iteration-list");
- for (i = 0; i < element.length; i ++) {
- option = element[i];
- var cls = option.getAttribute('class');
- switch(cls) {
- case "warning":
- option.style.backgroundColor = "yellow";
- option.style.color = "black";
- break;
- case "skip":
- option.style.backgroundColor = "silver";
- option.style.color = "black";
- break;
- case "fail":
- option.style.backgroundColor = "red";
- option.style.color = "white";
- break;
- case "exception":
- option.style.backgroundColor = "blueviolet";
- option.style.color = "white";
- break;
- default:
- option.style.backgroundColor = "white";
- option.style.color = "black";
- break;
- }
-
- };
-}
-
-function selectIteration(iteration) {
- var selectElement = document.getElementById("sidebar-iteration-list");
- var docId = loadDocument(iteration);
- selectElement.selectedIndex = docId;
- updateIterationSelector(selectElement);
-}
-
-function loadDocument(fileId) {
- var result = 0;
- if(fileId == 'M') {
- document.getElementById("main-view").src = "iterations/setup.html";
- } else {
- var id = pad(fileId, 3);
- document.getElementById("main-view").src = "iterations/iteration_" + id + ".html";
- result = parseInt(fileId);
- }
- return result;
-}
-
-function updateIterationSelector(element) {
- var index = element.selectedIndex
- var option_class = element[index].getAttribute('class')
- if (option_class != null) {
- element.setAttribute('class', "sidebar-iteration-list " + option_class);
- } else {
- element.setAttribute('class', "sidebar-iteration-list");
- }
-}
-
-function errorSelected(selectorId) {
- var newLocation = document.getElementById(selectorId).value;
- window.location.hash = newLocation;
-}
-
-function pad(strNumber, padding) {
- while((strNumber.length + 1) <= padding) {
- strNumber = "0" + strNumber;
- }
- return strNumber;
-}
-
-function showHide(id) {
- var ulElement = document.getElementById(id);
- if(ulElement.style.display == 'none') {
- ulElement.style.display = '';
- } else {
- ulElement.style.display = 'none';
- }
-}
-
-function chapterClick(id) {
- var id_array = id.split('.');
- var node_id = "";
- var i = 0;
- var destinationElement = document.getElementById(id);
- if (destinationElement.style.display == 'none') {
- do {
- node_id += id_array[i];
- var ele = document.getElementById(node_id);
- ele.style.display = '';
- node_id += '.';
- i += 1;
- } while (i < id_array.length);
- window.location = '#' + id;
- } else {
- destinationElement.style.display = 'none';
- }
-}
diff --git a/test/functional/test-framework/storage_devices/device.py b/test/functional/test-framework/storage_devices/device.py
deleted file mode 100644
index 566f403..0000000
--- a/test/functional/test-framework/storage_devices/device.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import posixpath
-
-from core.test_run import TestRun
-from test_tools import disk_utils, fs_utils
-from test_tools.disk_utils import get_device_filesystem_type, get_sysfs_path
-from test_utils.io_stats import IoStats
-from test_utils.size import Size, Unit
-
-
-class Device:
- def __init__(self, path):
- disk_utils.validate_dev_path(path)
- self.path = path
- self.size = Size(disk_utils.get_size(self.get_device_id()), Unit.Byte)
- self.filesystem = get_device_filesystem_type(self.get_device_id())
- self.mount_point = None
-
- def create_filesystem(self, fs_type: disk_utils.Filesystem, force=True, blocksize=None):
- disk_utils.create_filesystem(self, fs_type, force, blocksize)
- self.filesystem = fs_type
-
- def wipe_filesystem(self, force=True):
- disk_utils.wipe_filesystem(self, force)
- self.filesystem = None
-
- def is_mounted(self):
- output = TestRun.executor.run(f"findmnt {self.path}")
- if output.exit_code != 0:
- return False
- else:
- mount_point_line = output.stdout.split('\n')[1]
- device_path = fs_utils.readlink(self.path)
- self.mount_point = mount_point_line[0:mount_point_line.find(device_path)].strip()
- return True
-
- def mount(self, mount_point, options: [str] = None):
- if not self.is_mounted():
- if disk_utils.mount(self, mount_point, options):
- self.mount_point = mount_point
- else:
- raise Exception(f"Device is already mounted! Actual mount point: {self.mount_point}")
-
- def unmount(self):
- if not self.is_mounted():
- TestRun.LOGGER.info("Device is not mounted.")
- elif disk_utils.unmount(self):
- self.mount_point = None
-
- def get_device_link(self, directory: str):
- items = self.get_all_device_links(directory)
- return next(i for i in items if i.full_path.startswith(directory))
-
- def get_device_id(self):
- return fs_utils.readlink(self.path).split('/')[-1]
-
- def get_all_device_links(self, directory: str):
- from test_tools import fs_utils
- output = fs_utils.ls(f"$(find -L {directory} -samefile {self.path})")
- return fs_utils.parse_ls_output(output, self.path)
-
- def get_io_stats(self):
- return IoStats.get_io_stats(self.get_device_id())
-
- def get_sysfs_property(self, property_name):
- path = posixpath.join(disk_utils.get_sysfs_path(self.get_device_id()),
- "queue", property_name)
- return TestRun.executor.run_expect_success(f"cat {path}").stdout
-
- def set_sysfs_property(self, property_name, value):
- TestRun.LOGGER.info(
- f"Setting {property_name} for device {self.get_device_id()} to {value}.")
- path = posixpath.join(disk_utils.get_sysfs_path(self.get_device_id()), "queue",
- property_name)
- fs_utils.write_file(path, str(value))
-
- def set_max_io_size(self, new_max_io_size: Size):
- self.set_sysfs_property("max_sectors_kb",
- int(new_max_io_size.get_value(Unit.KibiByte)))
-
- def get_max_io_size(self):
- return Size(int(self.get_sysfs_property("max_sectors_kb")), Unit.KibiByte)
-
- def get_max_hw_io_size(self):
- return Size(int(self.get_sysfs_property("max_hw_sectors_kb")), Unit.KibiByte)
-
- def get_discard_granularity(self):
- return self.get_sysfs_property("discard_granularity")
-
- def get_discard_max_bytes(self):
- return self.get_sysfs_property("discard_max_bytes")
-
- def get_discard_zeroes_data(self):
- return self.get_sysfs_property("discard_zeroes_data")
-
- def get_numa_node(self):
- return int(TestRun.executor.run_expect_success(
- f"cat {get_sysfs_path(self.get_device_id())}/device/numa_node").stdout)
-
- def __str__(self):
- return (
- f'system path: {self.path}, short link: /dev/{self.get_device_id()},'
- f' filesystem: {self.filesystem}, mount point: {self.mount_point}, size: {self.size}'
- )
-
- def __repr__(self):
- return str(self)
-
- @staticmethod
- def get_scsi_debug_devices():
- scsi_debug_devices = TestRun.executor.run_expect_success(
- "lsscsi --scsi_id | grep scsi_debug").stdout
- return [Device(f'/dev/disk/by-id/scsi-{device.split()[-1]}')
- for device in scsi_debug_devices.splitlines()]
diff --git a/test/functional/test-framework/storage_devices/disk.py b/test/functional/test-framework/storage_devices/disk.py
deleted file mode 100644
index 83b8c9d..0000000
--- a/test/functional/test-framework/storage_devices/disk.py
+++ /dev/null
@@ -1,237 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import itertools
-import json
-import re
-from datetime import timedelta
-from enum import IntEnum
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_tools import disk_utils, fs_utils, nvme_cli
-from test_utils import disk_finder
-from test_utils.os_utils import wait
-from test_utils.size import Unit
-from test_tools.disk_utils import get_pci_address
-
-
-class DiskType(IntEnum):
- hdd = 0
- hdd4k = 1
- sata = 2
- nand = 3
- optane = 4
-
-
-class DiskTypeSetBase:
- def resolved(self):
- raise NotImplementedError()
-
- def types(self):
- raise NotImplementedError()
-
- def json(self):
- return json.dumps({
- "type": "set",
- "values": [t.name for t in self.types()]
- })
-
- def __lt__(self, other):
- return min(self.types()) < min(other.types())
-
- def __le__(self, other):
- return min(self.types()) <= min(other.types())
-
- def __eq__(self, other):
- return min(self.types()) == min(other.types())
-
- def __ne__(self, other):
- return min(self.types()) != min(other.types())
-
- def __gt__(self, other):
- return min(self.types()) > min(other.types())
-
- def __ge__(self, other):
- return min(self.types()) >= min(other.types())
-
-
-class DiskTypeSet(DiskTypeSetBase):
- def __init__(self, *args):
- self.__types = set(*args)
-
- def resolved(self):
- return True
-
- def types(self):
- return self.__types
-
-
-class DiskTypeLowerThan(DiskTypeSetBase):
- def __init__(self, disk_name):
- self.__disk_name = disk_name
-
- def resolved(self):
- return self.__disk_name in TestRun.disks
-
- def types(self):
- if not self.resolved():
- raise LookupError("Disk type not resolved!")
- disk_type = TestRun.disks[self.__disk_name].disk_type
- return set(filter(lambda d: d < disk_type, [*DiskType]))
-
- def json(self):
- return json.dumps({
- "type": "operator",
- "name": "lt",
- "args": [self.__disk_name]
- })
-
-
-class Disk(Device):
- def __init__(
- self,
- path,
- disk_type: DiskType,
- serial_number,
- block_size,
- ):
- Device.__init__(self, path)
- self.serial_number = serial_number
- self.block_size = Unit(block_size)
- self.disk_type = disk_type
- self.partitions = []
-
- def create_partitions(
- self,
- sizes: [],
- partition_table_type=disk_utils.PartitionTable.gpt):
- disk_utils.create_partitions(self, sizes, partition_table_type)
-
- def remove_partition(self, part):
- part_number = int(part.path.split("part")[1])
- disk_utils.remove_parition(self, part_number)
- self.partitions.remove(part)
-
- def umount_all_partitions(self):
- TestRun.LOGGER.info(
- f"Umounting all partitions from: {self.path}")
- cmd = f'umount -l {fs_utils.readlink(self.path)}*?'
- TestRun.executor.run(cmd)
-
- def remove_partitions(self):
- for part in self.partitions:
- if part.is_mounted():
- part.unmount()
- if disk_utils.remove_partitions(self):
- self.partitions.clear()
-
- def is_detected(self):
- if self.serial_number:
- serial_numbers = disk_finder.get_all_serial_numbers()
- return self.serial_number in serial_numbers
- elif self.path:
- output = fs_utils.ls_item(f"{self.path}")
- return fs_utils.parse_ls_output(output)[0] is not None
- raise Exception("Couldn't check if device is detected by the system")
-
- def wait_for_plug_status(self, should_be_visible):
- if not wait(lambda: should_be_visible == self.is_detected(),
- timedelta(minutes=1),
- timedelta(seconds=1)):
- raise Exception(f"Timeout occurred while trying to "
- f"{'plug' if should_be_visible else 'unplug'} disk.")
-
- def plug(self):
- if self.is_detected():
- return
- TestRun.executor.run_expect_success(self.plug_command)
- self.wait_for_plug_status(True)
-
- def unplug(self):
- if not self.is_detected():
- return
- TestRun.executor.run_expect_success(self.unplug_command)
- self.wait_for_plug_status(False)
-
- @staticmethod
- def plug_all_disks():
- TestRun.executor.run_expect_success(NvmeDisk.plug_all_command)
- TestRun.executor.run_expect_success(SataDisk.plug_all_command)
-
- def __str__(self):
- disk_str = f'system path: {self.path}, type: {self.disk_type.name}, ' \
- f'serial: {self.serial_number}, size: {self.size}, ' \
- f'block size: {self.block_size}, partitions:\n'
- for part in self.partitions:
- disk_str += f'\t{part}'
- return disk_str
-
- @staticmethod
- def create_disk(path,
- disk_type: DiskType,
- serial_number,
- block_size):
- if disk_type is DiskType.nand or disk_type is DiskType.optane:
- return NvmeDisk(path, disk_type, serial_number, block_size)
- else:
- return SataDisk(path, disk_type, serial_number, block_size)
-
-
-class NvmeDisk(Disk):
- plug_all_command = "echo 1 > /sys/bus/pci/rescan"
-
- def __init__(self, path, disk_type, serial_number, block_size):
- Disk.__init__(self, path, disk_type, serial_number, block_size)
- self.plug_command = NvmeDisk.plug_all_command
- self.unplug_command = f"echo 1 > /sys/block/{self.get_device_id()}/device/remove || " \
- f"echo 1 > /sys/block/{self.get_device_id()}/device/device/remove"
- self.pci_address = get_pci_address(self.get_device_id())
-
- def __str__(self):
- disk_str = super().__str__()
- disk_str = f"pci address: {self.pci_address}, " + disk_str
- return disk_str
-
- def format_disk(self, metadata_size=None, block_size=None,
- force=True, format_params=None, reset=True):
- nvme_cli.format_disk(self, metadata_size, block_size, force, format_params, reset)
-
- def get_lba_formats(self):
- return nvme_cli.get_lba_formats(self)
-
- def get_lba_format_in_use(self):
- return nvme_cli.get_lba_format_in_use(self)
-
-
-class SataDisk(Disk):
- plug_all_command = "for i in $(find -H /sys/devices/ -path '*/scsi_host/*/scan' -type f); " \
- "do echo '- - -' > $i; done;"
-
- def __init__(self, path, disk_type, serial_number, block_size):
- Disk.__init__(self, path, disk_type, serial_number, block_size)
- self.plug_command = SataDisk.plug_all_command
- self.unplug_command = \
- f"echo 1 > {self.get_sysfs_properties(self.get_device_id()).full_path}/device/delete"
-
- def get_sysfs_properties(self, device_id):
- ls_command = f"$(find -H /sys/devices/ -name {device_id} -type d)"
- output = fs_utils.ls_item(f"{ls_command}")
- sysfs_addr = fs_utils.parse_ls_output(output)[0]
- if not sysfs_addr:
- raise Exception(f"Failed to find sysfs address: ls -l {ls_command}")
- dirs = sysfs_addr.full_path.split('/')
- scsi_address = dirs[-3]
- matches = re.search(
- r"^(?P\d+)[-:](?P\d+)[-:](?P\d+)[-:](?P\d+)$",
- scsi_address)
- controller_id = matches["controller"]
- port_id = matches["port"]
- target_id = matches["target"]
- lun = matches["lun"]
-
- host_path = "/".join(itertools.takewhile(lambda x: not x.startswith("host"), dirs))
- self.plug_command = f"echo '{port_id} {target_id} {lun}' > " \
- f"{host_path}/host{controller_id}/scsi_host/host{controller_id}/scan"
- return sysfs_addr
diff --git a/test/functional/test-framework/storage_devices/drbd.py b/test/functional/test-framework/storage_devices/drbd.py
deleted file mode 100644
index 66baeda..0000000
--- a/test/functional/test-framework/storage_devices/drbd.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause-Clear
-#
-
-import os
-import posixpath
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_tools.drbdadm import Drbdadm
-from test_utils.filesystem.symlink import Symlink
-from test_utils.output import CmdException
-
-
-class Drbd(Device):
- def __init__(self, config):
- if Drbdadm.dump_config(config.name).exit_code != 0:
- raise ValueError(f"Resource {config.name} not found")
- self.config = config
-
- def create_metadata(self, force):
- return Drbdadm.create_metadata(self.config.name, force)
-
- def up(self):
- output = Drbdadm.up(self.config.name)
- if output.exit_code != 0:
- raise CmdException(f"Failed to create {self.config.name} drbd instance")
-
- self.path = posixpath.join("/dev/disk/by-id/", posixpath.basename(self.config.device))
- self.symlink = Symlink.get_symlink(self.path, self.config.device, True)
- self.device = Device(self.path)
-
- return self.device
-
- def wait_for_sync(self):
- return Drbdadm.wait_for_sync(self.config.name)
-
- def is_in_sync(self):
- return Drbdadm.in_sync(self.config.name)
-
- def get_status(self):
- return Drbdadm.get_status(self.config.name)
-
- def set_primary(self, force=False):
- return Drbdadm.set_node_primary(self.config.name, force)
-
- def down(self):
- output = Drbdadm.down(self.config.name)
- if output.exit_code != 0:
- raise CmdException(f"Failed to stop {self.config.name} drbd instance")
-
- self.device = None
- self.symlink.remove(True, True)
-
- @staticmethod
- def down_all():
- try:
- Drbdadm.down_all()
- except CmdException as e:
- if "no resources defined" not in str(e):
- raise e
-
- @staticmethod
- def is_installed():
- return TestRun.executor.run("which drbdadm && modinfo drbd").exit_code == 0
diff --git a/test/functional/test-framework/storage_devices/lvm.py b/test/functional/test-framework/storage_devices/lvm.py
deleted file mode 100644
index b1cfa88..0000000
--- a/test/functional/test-framework/storage_devices/lvm.py
+++ /dev/null
@@ -1,531 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import threading
-
-from typing import Union
-
-from api.cas.core import Core
-from core.test_run import TestRun
-from storage_devices.device import Device
-from storage_devices.disk import Disk, NvmeDisk
-from storage_devices.partition import Partition
-from test_tools.fs_utils import readlink
-from test_utils.disk_finder import resolve_to_by_id_link
-from test_utils.filesystem.symlink import Symlink
-from test_utils.size import Size
-
-lvm_config_path = "/etc/lvm/lvm.conf"
-filter_prototype_regex = r"^\sfilter\s=\s\["
-types_prototype_regex = r"^\stypes\s=\s\["
-global_filter_prototype_regex = r"^\sglobal_filter\s=\s\["
-tab = "\\\\t"
-
-
-class LvmConfiguration:
- def __init__(
- self,
- lvm_filters: [] = None,
- pv_num: int = None,
- vg_num: int = None,
- lv_num: int = None,
- cache_num: int = None,
- cas_dev_num: int = None
- ):
- self.lvm_filters = lvm_filters
- self.pv_num = pv_num
- self.vg_num = vg_num
- self.lv_num = lv_num
- self.cache_num = cache_num
- self.cas_dev_num = cas_dev_num
-
- @staticmethod
- def __read_definition_from_lvm_config(
- prototype_regex: str
- ):
- cmd = f"grep '{prototype_regex}' {lvm_config_path}"
- output = TestRun.executor.run(cmd).stdout
-
- return output
-
- @classmethod
- def __add_block_dev_to_lvm_config(
- cls,
- block_device_type: str,
- number_of_partitions: int = 16
- ):
- types_definition = cls.read_types_definition_from_lvm_config()
-
- if types_definition:
- if block_device_type in types_definition:
- TestRun.LOGGER.info(f"Device type '{block_device_type}' already present in config")
- return
-
- TestRun.LOGGER.info(f"Add block device type to existing list")
- new_type_prefix = f"types = [\"{block_device_type}\", {number_of_partitions}, "
-
- config_update_cmd = f"sed -i 's/{types_prototype_regex}/\t{new_type_prefix}/g'" \
- f" {lvm_config_path}"
- else:
- TestRun.LOGGER.info(f"Create new types variable")
- new_types = f"types = [\"{block_device_type}\", {number_of_partitions}]"
- characteristic_line = f"# Configuration option devices\\/sysfs_scan."
- config_update_cmd = f"sed -i /'{characteristic_line}'/i\\ '{tab}{new_types}' " \
- f"{lvm_config_path}"
-
- TestRun.LOGGER.info(f"Adding {block_device_type} ({number_of_partitions} partitions) "
- f"to supported types in {lvm_config_path}")
- TestRun.executor.run(config_update_cmd)
-
- @classmethod
- def __add_filter_to_lvm_config(
- cls,
- filter: str
- ):
- if filter is None:
- TestRun.LOGGER.error(f"Lvm filter for lvm config not provided.")
-
- filters_definition = cls.read_filter_definition_from_lvm_config()
-
- if filters_definition:
- if filter in filters_definition:
- TestRun.LOGGER.info(f"Filter definition '{filter}' already present in config")
- return
-
- new_filter_formatted = filter.replace("/", "\\/")
- new_filter_prefix = f"filter = [ \"{new_filter_formatted}\", "
-
- TestRun.LOGGER.info(f"Adding filter to existing list")
- config_update_cmd = f"sed -i 's/{filter_prototype_regex}/\t{new_filter_prefix}/g'" \
- f" {lvm_config_path}"
- else:
- TestRun.LOGGER.info(f"Create new filter variable")
- new_filter = f"filter = [\"{filter}\"]"
- characteristic_line = f"# Configuration option devices\\/global_filter."
- config_update_cmd = f"sed -i /'{characteristic_line}'/i\\ '{tab}{new_filter}' " \
- f"{lvm_config_path}"
-
- TestRun.LOGGER.info(f"Adding filter '{filter}' to {lvm_config_path}")
- TestRun.executor.run(config_update_cmd)
-
- @classmethod
- def read_types_definition_from_lvm_config(cls):
- return cls.__read_definition_from_lvm_config(types_prototype_regex)
-
- @classmethod
- def read_filter_definition_from_lvm_config(cls):
- return cls.__read_definition_from_lvm_config(filter_prototype_regex)
-
- @classmethod
- def read_global_filter_definition_from_lvm_config(cls):
- return cls.__read_definition_from_lvm_config(global_filter_prototype_regex)
-
- @classmethod
- def add_block_devices_to_lvm_config(
- cls,
- device_type: str
- ):
- if device_type is None:
- TestRun.LOGGER.error(f"No device provided.")
-
- cls.__add_block_dev_to_lvm_config(device_type)
-
- @classmethod
- def add_filters_to_lvm_config(
- cls,
- filters: []
- ):
- if filters is None:
- TestRun.LOGGER.error(f"Lvm filters for lvm config not provided.")
-
- for f in filters:
- cls.__add_filter_to_lvm_config(f)
-
- @classmethod
- def configure_dev_types_in_config(
- cls,
- devices: ([Device], Device)
- ):
- if isinstance(devices, list):
- devs = []
- for device in devices:
- dev = device.parent_device if isinstance(device, Partition) else device
- devs.append(dev)
-
- if any(isinstance(dev, Core) for dev in devs):
- cls.add_block_devices_to_lvm_config("cas")
- if any(isinstance(dev, NvmeDisk) for dev in devs):
- cls.add_block_devices_to_lvm_config("nvme")
- else:
- dev = devices.parent_device if isinstance(devices, Partition) else devices
- if isinstance(dev, Core):
- cls.add_block_devices_to_lvm_config("cas")
- if isinstance(dev, NvmeDisk):
- cls.add_block_devices_to_lvm_config("nvme")
-
- @classmethod
- def configure_filters(
- cls,
- lvm_filters: [],
- devices: ([Device], Device)
- ):
- if lvm_filters:
- TestRun.LOGGER.info(f"Preparing configuration for LVMs - filters.")
- LvmConfiguration.add_filters_to_lvm_config(lvm_filters)
-
- cls.configure_dev_types_in_config(devices)
-
- @staticmethod
- def remove_global_filter_from_config():
- cmd = f"sed -i '/{global_filter_prototype_regex}/d' {lvm_config_path}"
- TestRun.executor.run(cmd)
-
- @staticmethod
- def remove_filters_from_config():
- cmd = f"sed -i '/{filter_prototype_regex}/d' {lvm_config_path}"
- TestRun.executor.run(cmd)
-
-
-class VolumeGroup:
- __unique_vg_id = 0
- __lock = threading.Lock()
-
- def __init__(self, name: str = None):
- self.name = name
-
- def __eq__(self, other):
- try:
- return self.name == other.name
- except AttributeError:
- return False
-
- @classmethod
- def __get_vg_name(cls, prefix: str = "vg"):
- with cls.__lock:
- cls.__unique_vg_id += 1
- return f"{prefix}{cls.__unique_vg_id}"
-
- @staticmethod
- def get_all_volume_groups():
- output_lines = TestRun.executor.run(f"pvscan").stdout.splitlines()
-
- volume_groups = {}
- for line in output_lines:
- if "PV" not in line:
- continue
-
- line_elements = line.split()
- pv = line_elements[line_elements.index("PV") + 1]
- vg = ""
- if "VG" in line:
- vg = line_elements[line_elements.index("VG") + 1]
-
- if vg not in volume_groups:
- volume_groups[vg] = []
- volume_groups[vg].append(pv)
-
- return volume_groups
-
- @staticmethod
- def create_vg(vg_name: str, device_paths: str):
- if not vg_name:
- raise ValueError("Name needed for VG creation.")
- if not device_paths:
- raise ValueError("Device paths needed for VG creation.")
-
- cmd = f"vgcreate --yes {vg_name} {device_paths} "
- TestRun.executor.run_expect_success(cmd)
-
- @classmethod
- def is_vg_already_present(cls, dev_number: int, device_paths: str = None):
- if not device_paths:
- TestRun.LOGGER.exception("No devices provided.")
-
- volume_groups = cls.get_all_volume_groups()
-
- for vg in volume_groups:
- for pv in volume_groups[vg]:
- if len(volume_groups[vg]) == dev_number and pv in device_paths:
- return cls(vg)
-
- for vg in volume_groups:
- for pv in volume_groups[vg]:
- if pv in device_paths:
- TestRun.LOGGER.warning(f"Some devices are used in other LVM volume group")
- return False
-
- @classmethod
- def create(cls, device_paths: str = None):
- vg_name = cls.__get_vg_name()
-
- VolumeGroup.create_vg(vg_name, device_paths)
-
- volume_groups = VolumeGroup.get_all_volume_groups()
-
- if vg_name in volume_groups:
- return cls(vg_name)
- else:
- TestRun.LOGGER.error("Had not found newly created VG.")
-
- @staticmethod
- def remove(vg_name: str):
- if not vg_name:
- raise ValueError("Name needed for VG remove operation.")
-
- cmd = f"vgremove {vg_name}"
- return TestRun.executor.run(cmd)
-
- @staticmethod
- def get_logical_volumes_path(vg_name: str):
- cmd = f"lvdisplay | grep /dev/{vg_name}/ | awk '{{print $3}}'"
- paths = TestRun.executor.run(cmd).stdout.splitlines()
-
- return paths
-
-
-class Lvm(Disk):
- __unique_lv_id = 0
- __lock = threading.Lock()
-
- def __init__(
- self,
- path_dm: str, # device mapper path
- volume_group: VolumeGroup,
- volume_name: str = None
- ):
- Device.__init__(self, resolve_to_by_id_link(path_dm))
- self.device_name = path_dm.split('/')[-1]
- self.volume_group = volume_group
- self.volume_name = volume_name
-
- def __eq__(self, other):
- try:
- return self.device_name == other.device_name and \
- self.volume_group == other.volume_group and \
- self.volume_name == other.volume_name
- except AttributeError:
- return False
-
- @classmethod
- def __get_unique_lv_name(cls, prefix: str = "lv"):
- with cls.__lock:
- cls.__unique_lv_id += 1
- return f"{prefix}{cls.__unique_lv_id}"
-
- @classmethod
- def __create(
- cls,
- name: str,
- volume_size_cmd: str,
- volume_group: VolumeGroup
- ):
- TestRun.LOGGER.info(f"Creating LV '{name}'.")
- cmd = f"lvcreate {volume_size_cmd} --name {name} {volume_group.name} --yes"
- TestRun.executor.run_expect_success(cmd)
-
- volumes = cls.discover_logical_volumes()
- for volume in volumes:
- if name == volume.volume_name:
- return volume
-
- @classmethod
- def configure_global_filter(
- cls,
- dev_first: Device,
- lv_amount: int,
- pv_devs: ([Device], Device)
- ):
- device_first = dev_first.parent_device if isinstance(dev_first, Partition) else dev_first
- if lv_amount > 1 and isinstance(device_first, Core):
-
- global_filter_def = LvmConfiguration.read_global_filter_definition_from_lvm_config()
- if not isinstance(pv_devs, list):
- pv_devs = [pv_devs]
-
- if global_filter_def:
- TestRun.LOGGER.info(f"Configure 'global filter' variable")
- links = []
- for pv_dev in pv_devs:
- link = pv_dev.get_device_link("/dev/disk/by-id")
- links.append(str(link))
-
- for link in links:
- if link in global_filter_def:
- TestRun.LOGGER.info(f"Global filter definition already contains '{link}'")
- continue
-
- new_link_formatted = link.replace("/", "\\/")
- new_global_filter_prefix = f"global_filter = [ \"r|{new_link_formatted}|\", "
-
- TestRun.LOGGER.info(f"Adding global filter '{link}' to existing list")
- config_update_cmd = f"sed -i 's/{global_filter_prototype_regex}/\t" \
- f"{new_global_filter_prefix}/g' {lvm_config_path}"
- TestRun.executor.run(config_update_cmd)
- else:
- for pv_dev in pv_devs:
- link = pv_dev.get_device_link("/dev/disk/by-id")
- global_filter = f"\"r|{link}|\""
- global_filter += ", "
- global_filter = global_filter[:-2]
-
- TestRun.LOGGER.info(f"Create new 'global filter' variable")
-
- new_global = f"global_filter = [{global_filter}]"
- characteristic_line = f"# Configuration option devices\\/types."
- config_update_cmd = f"sed -i /'{characteristic_line}'/i\\ " \
- f"'{tab}{new_global}' {lvm_config_path}"
-
- TestRun.LOGGER.info(f"Adding global filter '{global_filter}' to {lvm_config_path}")
- TestRun.executor.run(config_update_cmd)
-
- TestRun.LOGGER.info(f"Remove 'filter' in order to 'global_filter' to be used")
- if LvmConfiguration.read_filter_definition_from_lvm_config():
- LvmConfiguration.remove_filters_from_config()
-
- @classmethod
- def create_specific_lvm_configuration(
- cls,
- devices: ([Device], Device),
- lvm_configuration: LvmConfiguration,
- lvm_as_core: bool = False
- ):
- pv_per_vg = int(lvm_configuration.pv_num / lvm_configuration.vg_num)
- lv_per_vg = int(lvm_configuration.lv_num / lvm_configuration.vg_num)
- lv_size_percentage = int(100 / lv_per_vg)
-
- LvmConfiguration.configure_filters(lvm_configuration.lvm_filters, devices)
-
- logical_volumes = []
-
- for vg_iter in range(lvm_configuration.vg_num):
- if isinstance(devices, list):
- pv_devs = []
- start_range = vg_iter * pv_per_vg
- end_range = start_range + pv_per_vg
- for i in range(start_range, end_range):
- pv_devs.append(devices[i])
- device_first = devices[0]
- else:
- pv_devs = devices
- device_first = devices
-
- for j in range(lv_per_vg):
- lv = cls.create(lv_size_percentage, pv_devs)
- logical_volumes.append(lv)
-
- if lvm_as_core:
- cls.configure_global_filter(device_first, lv_per_vg, pv_devs)
-
- return logical_volumes
-
- @classmethod
- def create(
- cls,
- volume_size_or_percent: Union[Size, int],
- devices: ([Device], Device),
- name: str = None
- ):
- if isinstance(volume_size_or_percent, Size):
- size_cmd = f"--size {volume_size_or_percent.get_value()}B"
- elif isinstance(volume_size_or_percent, int):
- size_cmd = f"--extents {volume_size_or_percent}%VG"
- else:
- TestRun.LOGGER.error(f"Incorrect type of the first argument (volume_size_or_percent).")
-
- if not name:
- name = cls.__get_unique_lv_name()
-
- devices_paths = cls.get_devices_path(devices)
- dev_number = len(devices) if isinstance(devices, list) else 1
-
- vg = VolumeGroup.is_vg_already_present(dev_number, devices_paths)
-
- if not vg:
- vg = VolumeGroup.create(devices_paths)
-
- return cls.__create(name, size_cmd, vg)
-
- @staticmethod
- def get_devices_path(devices: ([Device], Device)):
- if isinstance(devices, list):
- return " ".join([Symlink(dev.path).get_target() for dev in devices])
- else:
- return Symlink(devices.path).get_target()
-
- @classmethod
- def discover_logical_volumes(cls):
- vol_groups = VolumeGroup.get_all_volume_groups()
- volumes = []
- for vg in vol_groups:
- lv_discovered = VolumeGroup.get_logical_volumes_path(vg)
- if lv_discovered:
- for lv_path in lv_discovered:
- cls.make_sure_lv_is_active(lv_path)
- lv_name = lv_path.split('/')[-1]
- volumes.append(
- cls(
- readlink(lv_path),
- VolumeGroup(vg),
- lv_name
- )
- )
- else:
- TestRun.LOGGER.info(f"No LVMs present in the system.")
-
- return volumes
-
- @classmethod
- def discover(cls):
- TestRun.LOGGER.info("Discover LVMs in system...")
- return cls.discover_logical_volumes()
-
- @staticmethod
- def remove(lv_name: str, vg_name: str):
- if not lv_name:
- raise ValueError("LV name needed for LV remove operation.")
- if not vg_name:
- raise ValueError("VG name needed for LV remove operation.")
-
- cmd = f"lvremove -f {vg_name}/{lv_name}"
- return TestRun.executor.run(cmd)
-
- @staticmethod
- def remove_pv(pv_name: str):
- if not pv_name:
- raise ValueError("Name needed for PV remove operation.")
-
- cmd = f"pvremove {pv_name}"
- return TestRun.executor.run(cmd)
-
- @classmethod
- def remove_all(cls):
- cmd = f"lvdisplay | grep 'LV Path' | awk '{{print $3}}'"
- lvm_paths = TestRun.executor.run(cmd).stdout.splitlines()
- for lvm_path in lvm_paths:
- lv_name = lvm_path.split('/')[-1]
- vg_name = lvm_path.split('/')[-2]
- cls.remove(lv_name, vg_name)
-
- cmd = f"vgdisplay | grep 'VG Name' | awk '{{print $3}}'"
- vg_names = TestRun.executor.run(cmd).stdout.splitlines()
- for vg_name in vg_names:
- TestRun.executor.run(f"vgchange -an {vg_name}")
- VolumeGroup.remove(vg_name)
-
- cmd = f"pvdisplay | grep 'PV Name' | awk '{{print $3}}'"
- pv_names = TestRun.executor.run(cmd).stdout.splitlines()
- for pv_name in pv_names:
- cls.remove_pv(pv_name)
-
- TestRun.LOGGER.info(f"Successfully removed all LVMs.")
-
- @staticmethod
- def make_sure_lv_is_active(lv_path: str):
- cmd = f"lvscan"
- output_lines = TestRun.executor.run_expect_success(cmd).stdout.splitlines()
-
- for line in output_lines:
- if "inactive " in line and lv_path in line:
- cmd = f"lvchange -ay {lv_path}"
- TestRun.executor.run_expect_success(cmd)
diff --git a/test/functional/test-framework/storage_devices/partition.py b/test/functional/test-framework/storage_devices/partition.py
deleted file mode 100644
index 080ab4c..0000000
--- a/test/functional/test-framework/storage_devices/partition.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from storage_devices.device import Device
-from test_tools import disk_utils
-from test_utils.size import Size
-
-
-class Partition(Device):
- def __init__(self, parent_dev, type, number, begin: Size, end: Size):
- Device.__init__(self, disk_utils.get_partition_path(parent_dev.path, number))
- self.number = number
- self.parent_device = parent_dev
- self.type = type
- self.begin = begin
- self.end = end
-
- def __str__(self):
- return f"\tsystem path: {self.path}, size: {self.size}, type: {self.type}, " \
- f"parent device: {self.parent_device.path}\n"
diff --git a/test/functional/test-framework/storage_devices/raid.py b/test/functional/test-framework/storage_devices/raid.py
deleted file mode 100644
index 4e3685c..0000000
--- a/test/functional/test-framework/storage_devices/raid.py
+++ /dev/null
@@ -1,182 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import threading
-from enum import IntEnum, Enum
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from storage_devices.disk import Disk
-from test_tools.fs_utils import readlink
-from test_tools.mdadm import Mdadm
-from test_utils.disk_finder import resolve_to_by_id_link
-from test_utils.size import Size, Unit
-
-
-def get_devices_paths_string(devices: [Device]):
- return " ".join([d.path for d in devices])
-
-
-class Level(IntEnum):
- Raid0 = 0
- Raid1 = 1
- Raid4 = 4
- Raid5 = 5
- Raid6 = 6
- Raid10 = 10
-
-
-class StripSize(IntEnum):
- Strip4K = 4
- Strip8K = 8
- Strip16K = 16
- Strip32K = 32
- Strip64K = 64
- Strip128K = 128
- Strip256K = 256
- Strip1M = 1024
-
-
-class MetadataVariant(Enum):
- Legacy = "legacy"
- Imsm = "imsm"
-
-
-class RaidConfiguration:
- def __init__(
- self,
- level: Level = None,
- metadata: MetadataVariant = MetadataVariant.Imsm,
- number_of_devices: int = 0,
- size: Size = None,
- strip_size: StripSize = None,
- name: str = None,
- ):
- self.level = level
- self.metadata = metadata
- self.number_of_devices = number_of_devices
- self.size = size
- self.strip_size = strip_size
- self.name = name
-
-
-class Raid(Disk):
- __unique_id = 0
- __lock = threading.Lock()
-
- def __init__(
- self,
- path: str,
- level: Level,
- uuid: str,
- container_uuid: str = None,
- container_path: str = None,
- metadata: MetadataVariant = MetadataVariant.Imsm,
- array_devices: [Device] = [],
- volume_devices: [Device] = [],
- ):
- Device.__init__(self, resolve_to_by_id_link(path.replace("/dev/", "")))
- self.device_name = path.split('/')[-1]
- self.level = level
- self.uuid = uuid
- self.container_uuid = container_uuid
- self.container_path = container_path
- self.metadata = metadata
- self.array_devices = array_devices if array_devices else volume_devices.copy()
- self.volume_devices = volume_devices
- self.partitions = []
- self.__block_size = None
-
- def __eq__(self, other):
- try:
- return self.uuid == other.uuid
- except AttributeError:
- return False
-
- @property
- def block_size(self):
- if not self.__block_size:
- self.__block_size = Unit(int(self.get_sysfs_property("logical_block_size")))
- return self.__block_size
-
- def stop(self):
- Mdadm.stop(self.path)
- if self.container_path:
- Mdadm.stop(self.container_path)
-
- @classmethod
- def discover(cls):
- TestRun.LOGGER.info("Discover RAIDs in system...")
- raids = []
- for raid in Mdadm.examine_result():
- raids.append(
- cls(
- raid["path"],
- Level[raid["level"]],
- raid["uuid"],
- raid["container"]["uuid"] if "container" in raid else None,
- raid["container"]["path"] if "container" in raid else None,
- MetadataVariant(raid["metadata"]),
- [Device(d) for d in raid["array_devices"]],
- [Device(d) for d in raid["devices"]]
- )
- )
-
- return raids
-
- @classmethod
- def create(
- cls,
- raid_configuration: RaidConfiguration,
- devices: [Device]
- ):
- import copy
- raid_conf = copy.deepcopy(raid_configuration)
-
- if not raid_conf.number_of_devices:
- raid_conf.number_of_devices = len(devices)
- elif len(devices) < raid_conf.number_of_devices:
- raise ValueError("RAID configuration requires at least "
- f"{raid_conf.number_of_devices} devices")
-
- md_dir_path = "/dev/md/"
- array_devices = devices
- volume_devices = devices[:raid_conf.number_of_devices]
-
- if raid_conf.metadata != MetadataVariant.Legacy:
- container_conf = RaidConfiguration(
- name=cls.__get_unique_name(raid_conf.metadata.value),
- metadata=raid_conf.metadata,
- number_of_devices=len(array_devices)
- )
- Mdadm.create(container_conf, get_devices_paths_string(array_devices))
-
- if not raid_conf.name:
- raid_conf.name = cls.__get_unique_name()
-
- Mdadm.create(raid_conf, get_devices_paths_string(volume_devices))
-
- raid_link = md_dir_path + raid_conf.name
- raid = [r for r in Mdadm.examine_result() if readlink(r["path"]) == readlink(raid_link)][0]
-
- return cls(
- raid["path"],
- raid_conf.level,
- raid["uuid"],
- raid["container"]["uuid"] if "container" in raid else None,
- raid["container"]["path"] if "container" in raid else None,
- raid_conf.metadata,
- array_devices,
- volume_devices
- )
-
- @staticmethod
- def remove_all():
- Mdadm.stop()
-
- @classmethod
- def __get_unique_name(cls, prefix: str = "Raid"):
- with cls.__lock:
- cls.__unique_id += 1
- return f"{prefix}{cls.__unique_id}"
diff --git a/test/functional/test-framework/storage_devices/ramdisk.py b/test/functional/test-framework/storage_devices/ramdisk.py
deleted file mode 100644
index 011b812..0000000
--- a/test/functional/test-framework/storage_devices/ramdisk.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright(c) 2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import posixpath
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_tools import disk_utils
-from test_tools.fs_utils import ls, parse_ls_output
-from test_utils.filesystem.symlink import Symlink
-from test_utils.os_utils import reload_kernel_module, unload_kernel_module, is_kernel_module_loaded
-from test_utils.size import Size, Unit
-
-
-class RamDisk(Device):
- _module = "brd"
-
- @classmethod
- def create(cls, disk_size: Size, disk_count: int = 1):
- if disk_count < 1:
- raise ValueError("Wrong number of RAM disks requested")
-
- TestRun.LOGGER.info("Configure RAM disks...")
- params = {
- "rd_size": int(disk_size.get_value(Unit.KiB)),
- "rd_nr": disk_count
- }
- reload_kernel_module(cls._module, params)
-
- if not cls._is_configured(disk_size, disk_count):
- raise EnvironmentError(f"Wrong RAM disk configuration after loading '{cls._module}' "
- "module")
-
- return cls.list()
-
- @classmethod
- def remove_all(cls):
- if not is_kernel_module_loaded(cls._module):
- return
-
- for ram_disk in cls._list_devices():
- TestRun.executor.run(f"umount {ram_disk.full_path}")
- link_path = posixpath.join("/dev/disk/by-id", ram_disk.name)
- try:
- link = Symlink.get_symlink(link_path=link_path, target=ram_disk.full_path)
- link.remove(force=True)
- except FileNotFoundError:
- pass
- TestRun.LOGGER.info("Removing RAM disks...")
- unload_kernel_module(cls._module)
-
- @classmethod
- def list(cls):
- ram_disks = []
- for ram_disk in cls._list_devices():
- link_path = posixpath.join("/dev/disk/by-id", ram_disk.name)
- link = Symlink.get_symlink(
- link_path=link_path, target=ram_disk.full_path, create=True
- )
- ram_disks.append(cls(link.full_path))
-
- return ram_disks
-
- @classmethod
- def _is_configured(cls, disk_size: Size, disk_count: int):
- ram_disks = cls._list_devices()
- return (
- len(ram_disks) >= disk_count
- and Size(disk_utils.get_size(ram_disks[0].name), Unit.Byte).align_down(Unit.MiB.value)
- == disk_size.align_down(Unit.MiB.value)
- )
-
- @staticmethod
- def _list_devices():
- ls_ram_disks = ls("/dev/ram*")
- if "No such file or directory" in ls_ram_disks:
- return []
- return parse_ls_output(ls_ram_disks)
diff --git a/test/functional/test-framework/test_tools/__init__.py b/test/functional/test-framework/test_tools/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/test_tools/blktrace.py b/test/functional/test-framework/test_tools/blktrace.py
deleted file mode 100644
index c9c5653..0000000
--- a/test/functional/test-framework/test_tools/blktrace.py
+++ /dev/null
@@ -1,225 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import math
-
-from aenum import IntFlag, Enum
-
-from datetime import timedelta
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_utils.filesystem.directory import Directory
-from test_utils.os_utils import is_mounted, drop_caches, DropCachesMode
-from test_utils.size import Size, Unit
-
-DEBUGFS_MOUNT_POINT = "/sys/kernel/debug"
-PREFIX = "trace_"
-HEADER_FORMAT = "%a|%C|%d|%e|%n|%N|%S|%5T.%9t\\n"
-
-
-class BlkTraceMask(IntFlag):
- read = 1
- write = 1 << 1
- flush = 1 << 2
- sync = 1 << 3
- queue = 1 << 4
- requeue = 1 << 5
- issue = 1 << 6
- complete = 1 << 7
- fs = 1 << 8
- pc = 1 << 9
- notify = 1 << 10
- ahead = 1 << 11
- meta = 1 << 12
- discard = 1 << 13
- drv_data = 1 << 14
- fua = 1 << 15
-
-
-class ActionKind(Enum):
- IoDeviceRemap = "A"
- IoBounce = "B"
- IoCompletion = "C"
- IoToDriver = "D"
- IoFrontMerge = "F"
- GetRequest = "G"
- IoInsert = "I"
- IoMerge = "M"
- PlugRequest = "P"
- IoHandled = "Q"
- RequeueRequest = "R"
- SleepRequest = "S"
- TimeoutUnplug = "T" # old version of TimerUnplug
- UnplugRequest = "U"
- TimerUnplug = "UT"
- Split = "X"
-
-
-class RwbsKind(IntFlag):
- Undefined = 0
- R = 1 # Read
- W = 1 << 1 # Write
- D = 1 << 2 # Discard
- F = 1 << 3 # Flush
- S = 1 << 4 # Synchronous
- M = 1 << 5 # Metadata
- A = 1 << 6 # Read Ahead
- N = 1 << 7 # None of the above
-
- def __str__(self):
- ret = []
- if self & RwbsKind.R:
- ret.append("read")
- if self & RwbsKind.W:
- ret.append("write")
- if self & RwbsKind.D:
- ret.append("discard")
- if self & RwbsKind.F:
- ret.append("flush")
- if self & RwbsKind.S:
- ret.append("sync")
- if self & RwbsKind.M:
- ret.append("metadata")
- if self & RwbsKind.A:
- ret.append("readahead")
- if self & RwbsKind.N:
- ret.append("none")
-
- return "|".join(ret)
-
-
-class BlkTrace:
- def __init__(self, device: Device, *masks: BlkTraceMask):
- self._mount_debugfs()
- if device is None:
- raise Exception("Device not provided")
- self.device = device
- self.masks = "" if not masks else f' -a {" -a ".join([m.name for m in masks])}'
- self.blktrace_pid = -1
- self.__outputDirectoryPath = None
-
- @staticmethod
- def _mount_debugfs():
- if not is_mounted(DEBUGFS_MOUNT_POINT):
- TestRun.executor.run_expect_success(f"mount -t debugfs none {DEBUGFS_MOUNT_POINT}")
-
- def start_monitoring(self, buffer_size: Size = None, number_of_subbuffers: int = None):
- if self.blktrace_pid != -1:
- raise Exception(f"blktrace already running with PID: {self.blktrace_pid}")
-
- self.__outputDirectoryPath = Directory.create_temp_directory().full_path
-
- drop_caches(DropCachesMode.ALL)
-
- number_of_subbuffers = ("" if number_of_subbuffers is None
- else f" --num-sub-buffers={number_of_subbuffers}")
- buffer_size = ("" if buffer_size is None
- else f" --buffer-size={buffer_size.get_value(Unit.KibiByte)}")
- command = (f"blktrace{number_of_subbuffers}{buffer_size} --dev={self.device.path}"
- f"{self.masks} --output={PREFIX} --output-dir={self.__outputDirectoryPath}")
- echo_output = TestRun.executor.run_expect_success(
- f"nohup {command} {self.__outputDirectoryPath}/out & echo $!"
- )
- self.blktrace_pid = int(echo_output.stdout)
- TestRun.LOGGER.info(f"blktrace monitoring for device {self.device.path} started"
- f" (PID: {self.blktrace_pid}, output dir: {self.__outputDirectoryPath}")
-
- def stop_monitoring(self):
- if self.blktrace_pid == -1:
- raise Exception("PID for blktrace is not set - has monitoring been started?")
-
- drop_caches(DropCachesMode.ALL)
-
- TestRun.executor.run_expect_success(f"kill -s SIGINT {self.blktrace_pid}")
- self.blktrace_pid = -1
-
- # dummy command for swallowing output of killed command
- TestRun.executor.run("sleep 2 && echo dummy")
- TestRun.LOGGER.info(f"blktrace monitoring for device {self.device.path} stopped")
-
- return self.__parse_blktrace_output()
-
- def __parse_blktrace_output(self):
- TestRun.LOGGER.info(f"Parsing blktrace headers from {self.__outputDirectoryPath}... "
- "Be patient")
- command = (f'blkparse --input-dir={self.__outputDirectoryPath} --input={PREFIX} '
- f'--format="{HEADER_FORMAT}"')
- blkparse_output = TestRun.executor.run_expect_success(
- command, timeout=timedelta(minutes=60)
- )
- parsed_headers = []
- for line in blkparse_output.stdout.splitlines():
- # At the end per-cpu summary is posted - there is no need for it now
- if line.startswith('CPU'):
- break
-
- header = Header.parse(line)
- if header is None:
- continue
- parsed_headers.append(header)
- TestRun.LOGGER.info(
- f"Parsed {len(parsed_headers)} blktrace headers from {self.__outputDirectoryPath}"
- )
- parsed_headers.sort(key=lambda x: x.timestamp)
- return parsed_headers
-
-
-class Header:
- def __init__(self):
- self.action = None
- self.block_count = None
- self.byte_count = None
- self.command = None
- self.error_value = None
- self.rwbs = RwbsKind.Undefined
- self.sector_number = None
- self.timestamp = None
-
- @staticmethod
- def parse(header_line: str):
- # messages/notifies are not formatted according to --format
- # so should be ignored (or parsed using standard format):
- if "m N" in header_line:
- return None
-
- header_fields = header_line.split('|')
- if len(header_fields) != 8:
- return None
-
- timestamp_fields = header_fields[7].split('.')
- timestamp_nano = int(timestamp_fields[-1]) if len(timestamp_fields) == 2 else 0
-
- header = Header()
- header.action = ActionKind(header_fields[0])
- header.command = header_fields[1]
- if len(header_fields[2]):
- header.rwbs = RwbsKind['|'.join(list(header_fields[2]))]
- header.error_value = int(header_fields[3])
- header.block_count = int(header_fields[4])
- header.byte_count = int(header_fields[5])
- header.sector_number = int(header_fields[6])
- header.timestamp = int(timestamp_fields[0]) * math.pow(10, 9) + timestamp_nano
-
- return header
-
- def __str__(self):
- ret = []
- if self.action:
- ret.append(f"action: {self.action.name}")
- if self.block_count:
- ret.append(f"block_count: {self.block_count}")
- if self.byte_count:
- ret.append(f"byte_count: {self.byte_count}")
- if self.command:
- ret.append(f"command: {self.command}")
- if self.error_value:
- ret.append(f"error_value: {self.error_value}")
- if self.rwbs:
- ret.append(f"rwbs: {self.rwbs}")
- if self.sector_number:
- ret.append(f"sector_number: {self.sector_number}")
- if self.timestamp:
- ret.append(f"timestamp: {self.timestamp}")
- return " ".join(ret)
diff --git a/test/functional/test-framework/test_tools/checksec.sh b/test/functional/test-framework/test_tools/checksec.sh
deleted file mode 100644
index dd1f72e..0000000
--- a/test/functional/test-framework/test_tools/checksec.sh
+++ /dev/null
@@ -1,882 +0,0 @@
-#!/bin/bash
-#
-# The BSD License (http://www.opensource.org/licenses/bsd-license.php)
-# specifies the terms and conditions of use for checksec.sh:
-#
-# Copyright (c) 2009-2011, Tobias Klein.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Tobias Klein nor the name of trapkit.de may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
-# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-# DAMAGE.
-#
-# Name : checksec.sh
-# Version : 1.5
-# Author : Tobias Klein
-# Date : November 2011
-# Download: http://www.trapkit.de/tools/checksec.html
-# Changes : http://www.trapkit.de/tools/checksec_changes.txt
-#
-# Description:
-#
-# Modern Linux distributions offer some mitigation techniques to make it
-# harder to exploit software vulnerabilities reliably. Mitigations such
-# as RELRO, NoExecute (NX), Stack Canaries, Address Space Layout
-# Randomization (ASLR) and Position Independent Executables (PIE) have
-# made reliably exploiting any vulnerabilities that do exist far more
-# challenging. The checksec.sh script is designed to test what *standard*
-# Linux OS and PaX (http://pax.grsecurity.net/) security features are being
-# used.
-#
-# As of version 1.3 the script also lists the status of various Linux kernel
-# protection mechanisms.
-#
-# Credits:
-#
-# Thanks to Brad Spengler (grsecurity.net) for the PaX support.
-# Thanks to Jon Oberheide (jon.oberheide.org) for the kernel support.
-# Thanks to Ollie Whitehouse (Research In Motion) for rpath/runpath support.
-#
-# Others that contributed to checksec.sh (in no particular order):
-#
-# Simon Ruderich, Denis Scherbakov, Stefan Kuttler, Radoslaw Madej,
-# Anthony G. Basile, Martin Vaeth and Brian Davis.
-#
-
-# global vars
-have_readelf=1
-verbose=false
-
-# FORTIFY_SOURCE vars
-FS_end=_chk
-FS_cnt_total=0
-FS_cnt_checked=0
-FS_cnt_unchecked=0
-FS_chk_func_libc=0
-FS_functions=0
-FS_libc=0
-
-# version information
-version() {
- echo "checksec v1.5, Tobias Klein, www.trapkit.de, November 2011"
- echo
-}
-
-# help
-help() {
- echo "Usage: checksec [OPTION]"
- echo
- echo "Options:"
- echo
- echo " --file "
- echo " --dir [-v]"
- echo " --proc "
- echo " --proc-all"
- echo " --proc-libs "
- echo " --kernel"
- echo " --fortify-file "
- echo " --fortify-proc "
- echo " --version"
- echo " --help"
- echo
- echo "For more information, see:"
- echo " http://www.trapkit.de/tools/checksec.html"
- echo
-}
-
-# check if command exists
-command_exists () {
- type $1 > /dev/null 2>&1;
-}
-
-# check if directory exists
-dir_exists () {
- if [ -d $1 ] ; then
- return 0
- else
- return 1
- fi
-}
-
-# check user privileges
-root_privs () {
- if [ $(/usr/bin/id -u) -eq 0 ] ; then
- return 0
- else
- return 1
- fi
-}
-
-# check if input is numeric
-isNumeric () {
- echo "$@" | grep -q -v "[^0-9]"
-}
-
-# check if input is a string
-isString () {
- echo "$@" | grep -q -v "[^A-Za-z]"
-}
-
-# check file(s)
-filecheck() {
- # check for RELRO support
- if readelf -l $1 2>/dev/null | grep -q 'GNU_RELRO'; then
- if readelf -d $1 2>/dev/null | grep -q 'BIND_NOW'; then
- echo -n -e '\033[32mFull RELRO \033[m '
- else
- echo -n -e '\033[33mPartial RELRO\033[m '
- fi
- else
- echo -n -e '\033[31mNo RELRO \033[m '
- fi
-
- # check for stack canary support
- if readelf -s $1 2>/dev/null | grep -q '__stack_chk_fail'; then
- echo -n -e '\033[32mCanary found \033[m '
- else
- echo -n -e '\033[31mNo canary found\033[m '
- fi
-
- # check for NX support
- if readelf -W -l $1 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then
- echo -n -e '\033[31mNX disabled\033[m '
- else
- echo -n -e '\033[32mNX enabled \033[m '
- fi
-
- # check for PIE support
- if readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
- echo -n -e '\033[31mNo PIE \033[m '
- elif readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then
- if readelf -d $1 2>/dev/null | grep -q '(DEBUG)'; then
- echo -n -e '\033[32mPIE enabled \033[m '
- else
- echo -n -e '\033[33mDSO \033[m '
- fi
- else
- echo -n -e '\033[33mNot an ELF file\033[m '
- fi
-
- # check for rpath / run path
- if readelf -d $1 2>/dev/null | grep -q 'rpath'; then
- echo -n -e '\033[31mRPATH \033[m '
- else
- echo -n -e '\033[32mNo RPATH \033[m '
- fi
-
- if readelf -d $1 2>/dev/null | grep -q 'runpath'; then
- echo -n -e '\033[31mRUNPATH \033[m '
- else
- echo -n -e '\033[32mNo RUNPATH \033[m '
- fi
-}
-
-# check process(es)
-proccheck() {
- # check for RELRO support
- if readelf -l $1/exe 2>/dev/null | grep -q 'Program Headers'; then
- if readelf -l $1/exe 2>/dev/null | grep -q 'GNU_RELRO'; then
- if readelf -d $1/exe 2>/dev/null | grep -q 'BIND_NOW'; then
- echo -n -e '\033[32mFull RELRO \033[m '
- else
- echo -n -e '\033[33mPartial RELRO \033[m '
- fi
- else
- echo -n -e '\033[31mNo RELRO \033[m '
- fi
- else
- echo -n -e '\033[31mPermission denied (please run as root)\033[m\n'
- exit 1
- fi
-
- # check for stack canary support
- if readelf -s $1/exe 2>/dev/null | grep -q 'Symbol table'; then
- if readelf -s $1/exe 2>/dev/null | grep -q '__stack_chk_fail'; then
- echo -n -e '\033[32mCanary found \033[m '
- else
- echo -n -e '\033[31mNo canary found \033[m '
- fi
- else
- if [ "$1" != "1" ] ; then
- echo -n -e '\033[33mPermission denied \033[m '
- else
- echo -n -e '\033[33mNo symbol table found\033[m '
- fi
- fi
-
- # first check for PaX support
- if cat $1/status 2> /dev/null | grep -q 'PaX:'; then
- pageexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b6) )
- segmexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b10) )
- mprotect=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b8) )
- randmmap=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b9) )
- if [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "R" ]] ; then
- echo -n -e '\033[32mPaX enabled\033[m '
- elif [[ "$pageexec" = "p" && "$segmexec" = "s" && "$randmmap" = "R" ]] ; then
- echo -n -e '\033[33mPaX ASLR only\033[m '
- elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "R" ]] ; then
- echo -n -e '\033[33mPaX mprot off \033[m'
- elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "r" ]] ; then
- echo -n -e '\033[33mPaX ASLR off\033[m '
- elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "r" ]] ; then
- echo -n -e '\033[33mPaX NX only\033[m '
- else
- echo -n -e '\033[31mPaX disabled\033[m '
- fi
- # fallback check for NX support
- elif readelf -W -l $1/exe 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then
- echo -n -e '\033[31mNX disabled\033[m '
- else
- echo -n -e '\033[32mNX enabled \033[m '
- fi
-
- # check for PIE support
- if readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
- echo -n -e '\033[31mNo PIE \033[m '
- elif readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then
- if readelf -d $1/exe 2>/dev/null | grep -q '(DEBUG)'; then
- echo -n -e '\033[32mPIE enabled \033[m '
- else
- echo -n -e '\033[33mDynamic Shared Object\033[m '
- fi
- else
- echo -n -e '\033[33mNot an ELF file \033[m '
- fi
-}
-
-# check mapped libraries
-libcheck() {
- libs=( $(awk '{ print $6 }' /proc/$1/maps | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /') )
-
- printf "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n"
-
- for element in $(seq 0 $((${#libs[@]} - 1)))
- do
- echo " ${libs[$element]}:"
- echo -n " "
- filecheck ${libs[$element]}
- printf "\n\n"
- done
-}
-
-# check for system-wide ASLR support
-aslrcheck() {
- # PaX ASLR support
- if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then
- echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n'
- echo -n -e ' Fallback to standard Linux ASLR check'
- fi
-
- if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then
- printf ": "
- if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then
- echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n'
- else
- echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n'
- fi
- else
- # standard Linux 'kernel.randomize_va_space' ASLR support
- # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description)
- printf " (kernel.randomize_va_space): "
- if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then
- echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n'
- printf " Description - Make the addresses of mmap base, stack and VDSO page randomized.\n"
- printf " This, among other things, implies that shared libraries will be loaded to \n"
- printf " random addresses. Also for PIE-linked binaries, the location of code start\n"
- printf " is randomized. Heap addresses are *not* randomized.\n\n"
- elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then
- echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n'
- printf " Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n"
- printf " This, among other things, implies that shared libraries will be loaded to random \n"
- printf " addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n"
- elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then
- echo -n -e '\033[31mOff (Setting: 0)\033[m\n'
- else
- echo -n -e '\033[31mNot supported\033[m\n'
- fi
- printf " See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n"
- fi
-}
-
-# check cpu nx flag
-nxcheck() {
- if grep -q nx /proc/cpuinfo; then
- echo -n -e '\033[32mYes\033[m\n\n'
- else
- echo -n -e '\033[31mNo\033[m\n\n'
- fi
-}
-
-# check for kernel protection mechanisms
-kernelcheck() {
- printf " Description - List the status of kernel protection mechanisms. Rather than\n"
- printf " inspect kernel mechanisms that may aid in the prevention of exploitation of\n"
- printf " userspace processes, this option lists the status of kernel configuration\n"
- printf " options that harden the kernel itself against attack.\n\n"
- printf " Kernel config: "
-
- if [ -f /proc/config.gz ] ; then
- kconfig="zcat /proc/config.gz"
- printf "\033[32m/proc/config.gz\033[m\n\n"
- elif [ -f /boot/config-`uname -r` ] ; then
- kconfig="cat /boot/config-`uname -r`"
- printf "\033[33m/boot/config-`uname -r`\033[m\n\n"
- printf " Warning: The config on disk may not represent running kernel config!\n\n";
- elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then
- kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config"
- printf "\033[33m%s\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config"
- printf " Warning: The config on disk may not represent running kernel config!\n\n";
- else
- printf "\033[31mNOT FOUND\033[m\n\n"
- exit 0
- fi
-
- printf " GCC stack protector support: "
- if $kconfig | grep -qi 'CONFIG_CC_STACKPROTECTOR=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Strict user copy checks: "
- if $kconfig | grep -qi 'CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Enforce read-only kernel data: "
- if $kconfig | grep -qi 'CONFIG_DEBUG_RODATA=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
- printf " Restrict /dev/mem access: "
- if $kconfig | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Restrict /dev/kmem access: "
- if $kconfig | grep -qi 'CONFIG_DEVKMEM=y'; then
- printf "\033[31mDisabled\033[m\n"
- else
- printf "\033[32mEnabled\033[m\n"
- fi
-
- printf "\n"
- printf "* grsecurity / PaX: "
-
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC=y'; then
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIGH=y'; then
- printf "\033[32mHigh GRKERNSEC\033[m\n\n"
- elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_MEDIUM=y'; then
- printf "\033[33mMedium GRKERNSEC\033[m\n\n"
- elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_LOW=y'; then
- printf "\033[31mLow GRKERNSEC\033[m\n\n"
- else
- printf "\033[33mCustom GRKERNSEC\033[m\n\n"
- fi
-
- printf " Non-executable kernel pages: "
- if $kconfig | grep -qi 'CONFIG_PAX_KERNEXEC=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Prevent userspace pointer deref: "
- if $kconfig | grep -qi 'CONFIG_PAX_MEMORY_UDEREF=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Prevent kobject refcount overflow: "
- if $kconfig | grep -qi 'CONFIG_PAX_REFCOUNT=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Bounds check heap object copies: "
- if $kconfig | grep -qi 'CONFIG_PAX_USERCOPY=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Disable writing to kmem/mem/port: "
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC_KMEM=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Disable privileged I/O: "
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC_IO=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Harden module auto-loading: "
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC_MODHARDEN=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
-
- printf " Hide kernel symbols: "
- if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIDESYM=y'; then
- printf "\033[32mEnabled\033[m\n"
- else
- printf "\033[31mDisabled\033[m\n"
- fi
- else
- printf "\033[31mNo GRKERNSEC\033[m\n\n"
- printf " The grsecurity / PaX patchset is available here:\n"
- printf " http://grsecurity.net/\n"
- fi
-
- printf "\n"
- printf "* Kernel Heap Hardening: "
-
- if $kconfig | grep -qi 'CONFIG_KERNHEAP=y'; then
- if $kconfig | grep -qi 'CONFIG_KERNHEAP_FULLPOISON=y'; then
- printf "\033[32mFull KERNHEAP\033[m\n\n"
- else
- printf "\033[33mPartial KERNHEAP\033[m\n\n"
- fi
- else
- printf "\033[31mNo KERNHEAP\033[m\n\n"
- printf " The KERNHEAP hardening patchset is available here:\n"
- printf " https://www.subreption.com/kernheap/\n\n"
- fi
-}
-
-# --- FORTIFY_SOURCE subfunctions (start) ---
-
-# is FORTIFY_SOURCE supported by libc?
-FS_libc_check() {
- printf "* FORTIFY_SOURCE support available (libc) : "
-
- if [ "${#FS_chk_func_libc[@]}" != "0" ] ; then
- printf "\033[32mYes\033[m\n"
- else
- printf "\033[31mNo\033[m\n"
- exit 1
- fi
-}
-
-# was the binary compiled with FORTIFY_SOURCE?
-FS_binary_check() {
- printf "* Binary compiled with FORTIFY_SOURCE support: "
-
- for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1)))
- do
- if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then
- printf "\033[32mYes\033[m\n"
- return
- fi
- done
- printf "\033[31mNo\033[m\n"
- exit 1
-}
-
-FS_comparison() {
- echo
- printf " ------ EXECUTABLE-FILE ------- . -------- LIBC --------\n"
- printf " FORTIFY-able library functions | Checked function names\n"
- printf " -------------------------------------------------------\n"
-
- for FS_elem_libc in $(seq 0 $((${#FS_chk_func_libc[@]} - 1)))
- do
- for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1)))
- do
- FS_tmp_func=${FS_functions[$FS_elem_functions]}
- FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]}
-
- if [[ $FS_tmp_func =~ ^$FS_tmp_libc$ ]] ; then
- printf " \033[31m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end
- let FS_cnt_total++
- let FS_cnt_unchecked++
- elif [[ $FS_tmp_func =~ ^$FS_tmp_libc(_chk) ]] ; then
- printf " \033[32m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end
- let FS_cnt_total++
- let FS_cnt_checked++
- fi
-
- done
- done
-}
-
-FS_summary() {
- echo
- printf "SUMMARY:\n\n"
- printf "* Number of checked functions in libc : ${#FS_chk_func_libc[@]}\n"
- printf "* Total number of library functions in the executable: ${#FS_functions[@]}\n"
- printf "* Number of FORTIFY-able functions in the executable : %s\n" $FS_cnt_total
- printf "* Number of checked functions in the executable : \033[32m%s\033[m\n" $FS_cnt_checked
- printf "* Number of unchecked functions in the executable : \033[31m%s\033[m\n" $FS_cnt_unchecked
- echo
-}
-
-# --- FORTIFY_SOURCE subfunctions (end) ---
-
-if !(command_exists readelf) ; then
- printf "\033[31mWarning: 'readelf' not found! It's required for most checks.\033[m\n\n"
- have_readelf=0
-fi
-
-# parse command-line arguments
-case "$1" in
-
- --version)
- version
- exit 0
- ;;
-
- --help)
- help
- exit 0
- ;;
-
- --dir)
- if [ "$3" = "-v" ] ; then
- verbose=true
- fi
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid directory.\033[m\n\n"
- exit 1
- fi
- # remove trailing slashes
- tempdir=`echo $2 | sed -e "s/\/*$//"`
- if [ ! -d $tempdir ] ; then
- printf "\033[31mError: The directory '$tempdir' does not exist.\033[m\n\n"
- exit 1
- fi
- cd $tempdir
- printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n"
- for N in [A-Za-z]*; do
- if [ "$N" != "[A-Za-z]*" ]; then
- # read permissions?
- if [ ! -r $N ]; then
- printf "\033[31mError: No read permissions for '$tempdir/$N' (run as root).\033[m\n"
- else
- # ELF executable?
- out=`file $N`
- if [[ ! $out =~ ELF ]] ; then
- if [ "$verbose" = "true" ] ; then
- printf "\033[34m*** Not an ELF file: $tempdir/"
- file $N
- printf "\033[m"
- fi
- else
- filecheck $N
- if [ `find $tempdir/$N \( -perm -004000 -o -perm -002000 \) -type f -print` ]; then
- printf "\033[37;41m%s%s\033[m" $2 $N
- else
- printf "%s%s" $tempdir/ $N
- fi
- echo
- fi
- fi
- fi
- done
- exit 0
- ;;
-
- --file)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid file.\033[m\n\n"
- exit 1
- fi
- # does the file exist?
- if [ ! -e $2 ] ; then
- printf "\033[31mError: The file '$2' does not exist.\033[m\n\n"
- exit 1
- fi
- # read permissions?
- if [ ! -r $2 ] ; then
- printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n"
- exit 1
- fi
- # ELF executable?
- out=`file $2`
- if [[ ! $out =~ ELF ]] ; then
- printf "\033[31mError: Not an ELF file: "
- file $2
- printf "\033[m\n"
- exit 1
- fi
- printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n"
- filecheck $2
- if [ `find $2 \( -perm -004000 -o -perm -002000 \) -type f -print` ] ; then
- printf "\033[37;41m%s%s\033[m" $2 $N
- else
- printf "%s" $2
- fi
- echo
- exit 0
- ;;
-
- --proc-all)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- cd /proc
- printf "* System-wide ASLR"
- aslrcheck
- printf "* Does the CPU support NX: "
- nxcheck
- printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n"
- for N in [1-9]*; do
- if [ $N != $$ ] && readlink -q $N/exe > /dev/null; then
- printf "%16s" `head -1 $N/status | cut -b 7-`
- printf "%7d " $N
- proccheck $N
- echo
- fi
- done
- if [ ! -e /usr/bin/id ] ; then
- printf "\n\033[33mNote: If you are running 'checksec.sh' as an unprivileged user, you\n"
- printf " will not see all processes. Please run the script as root.\033[m\n\n"
- else
- if !(root_privs) ; then
- printf "\n\033[33mNote: You are running 'checksec.sh' as an unprivileged user.\n"
- printf " Too see all processes, please run the script as root.\033[m\n\n"
- fi
- fi
- exit 0
- ;;
-
- --proc)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid process name.\033[m\n\n"
- exit 1
- fi
- if !(isString "$2") ; then
- printf "\033[31mError: Please provide a valid process name.\033[m\n\n"
- exit 1
- fi
- cd /proc
- printf "* System-wide ASLR"
- aslrcheck
- printf "* Does the CPU support NX: "
- nxcheck
- printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n"
- for N in `ps -Ao pid,comm | grep $2 | cut -b1-6`; do
- if [ -d $N ] ; then
- printf "%16s" `head -1 $N/status | cut -b 7-`
- printf "%7d " $N
- # read permissions?
- if [ ! -r $N/exe ] ; then
- if !(root_privs) ; then
- printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n"
- exit 1
- fi
- if [ ! `readlink $N/exe` ] ; then
- printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n"
- exit 1
- fi
- exit 1
- fi
- proccheck $N
- echo
- fi
- done
- exit 0
- ;;
-
- --proc-libs)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid process ID.\033[m\n\n"
- exit 1
- fi
- if !(isNumeric "$2") ; then
- printf "\033[31mError: Please provide a valid process ID.\033[m\n\n"
- exit 1
- fi
- cd /proc
- printf "* System-wide ASLR"
- aslrcheck
- printf "* Does the CPU support NX: "
- nxcheck
- printf "* Process information:\n\n"
- printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n"
- N=$2
- if [ -d $N ] ; then
- printf "%16s" `head -1 $N/status | cut -b 7-`
- printf "%7d " $N
- # read permissions?
- if [ ! -r $N/exe ] ; then
- if !(root_privs) ; then
- printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n"
- exit 1
- fi
- if [ ! `readlink $N/exe` ] ; then
- printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n"
- exit 1
- fi
- exit 1
- fi
- proccheck $N
- echo
- libcheck $N
- fi
- exit 0
- ;;
-
- --kernel)
- cd /proc
- printf "* Kernel protection information:\n\n"
- kernelcheck
- exit 0
- ;;
-
- --fortify-file)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid file.\033[m\n\n"
- exit 1
- fi
- # does the file exist?
- if [ ! -e $2 ] ; then
- printf "\033[31mError: The file '$2' does not exist.\033[m\n\n"
- exit 1
- fi
- # read permissions?
- if [ ! -r $2 ] ; then
- printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n"
- exit 1
- fi
- # ELF executable?
- out=`file $2`
- if [[ ! $out =~ ELF ]] ; then
- printf "\033[31mError: Not an ELF file: "
- file $2
- printf "\033[m\n"
- exit 1
- fi
- if [ -e /lib/libc.so.6 ] ; then
- FS_libc=/lib/libc.so.6
- elif [ -e /lib64/libc.so.6 ] ; then
- FS_libc=/lib64/libc.so.6
- elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then
- FS_libc=/lib/i386-linux-gnu/libc.so.6
- elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then
- FS_libc=/lib/x86_64-linux-gnu/libc.so.6
- else
- printf "\033[31mError: libc not found.\033[m\n\n"
- exit 1
- fi
-
- FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') )
- FS_functions=( $(readelf -s $2 | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') )
-
- FS_libc_check
- FS_binary_check
- FS_comparison
- FS_summary
-
- exit 0
- ;;
-
- --fortify-proc)
- if [ $have_readelf -eq 0 ] ; then
- exit 1
- fi
- if [ -z "$2" ] ; then
- printf "\033[31mError: Please provide a valid process ID.\033[m\n\n"
- exit 1
- fi
- if !(isNumeric "$2") ; then
- printf "\033[31mError: Please provide a valid process ID.\033[m\n\n"
- exit 1
- fi
- cd /proc
- N=$2
- if [ -d $N ] ; then
- # read permissions?
- if [ ! -r $N/exe ] ; then
- if !(root_privs) ; then
- printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n"
- exit 1
- fi
- if [ ! `readlink $N/exe` ] ; then
- printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n"
- exit 1
- fi
- exit 1
- fi
- if [ -e /lib/libc.so.6 ] ; then
- FS_libc=/lib/libc.so.6
- elif [ -e /lib64/libc.so.6 ] ; then
- FS_libc=/lib64/libc.so.6
- elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then
- FS_libc=/lib/i386-linux-gnu/libc.so.6
- elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then
- FS_libc=/lib/x86_64-linux-gnu/libc.so.6
- else
- printf "\033[31mError: libc not found.\033[m\n\n"
- exit 1
- fi
- printf "* Process name (PID) : %s (%d)\n" `head -1 $N/status | cut -b 7-` $N
- FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') )
- FS_functions=( $(readelf -s $2/exe | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') )
-
- FS_libc_check
- FS_binary_check
- FS_comparison
- FS_summary
- fi
- exit 0
- ;;
-
- *)
- if [ "$#" != "0" ] ; then
- printf "\033[31mError: Unknown option '$1'.\033[m\n\n"
- fi
- help
- exit 1
- ;;
-esac
diff --git a/test/functional/test-framework/test_tools/dd.py b/test/functional/test-framework/test_tools/dd.py
deleted file mode 100644
index 1ca51db..0000000
--- a/test/functional/test-framework/test_tools/dd.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import test_utils.linux_command as linux_comm
-import test_utils.size as size
-from core.test_run import TestRun
-
-
-class Dd(linux_comm.LinuxCommand):
- def __init__(self):
- linux_comm.LinuxCommand.__init__(self, TestRun.executor, 'dd')
-
- def block_size(self, value: size.Size):
- return self.set_param('bs', int(value.get_value()))
-
- def count(self, value):
- return self.set_param('count', value)
-
- def input(self, value):
- return self.set_param('if', value)
-
- def iflag(self, *values):
- return self.set_param('iflag', *values)
-
- def oflag(self, *values):
- return self.set_param('oflag', *values)
-
- def conv(self, *values):
- return self.set_param('conv', *values)
-
- def output(self, value):
- return self.set_param('of', value)
-
- def seek(self, value):
- return self.set_param('seek', value)
-
- def skip(self, value):
- return self.set_param('skip', value)
diff --git a/test/functional/test-framework/test_tools/ddrescue.py b/test/functional/test-framework/test_tools/ddrescue.py
deleted file mode 100644
index dfd3079..0000000
--- a/test/functional/test-framework/test_tools/ddrescue.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import test_utils.linux_command as linux_comm
-import test_utils.size as size
-from core.test_run import TestRun
-
-
-class Ddrescue(linux_comm.LinuxCommand):
- def __init__(self):
- linux_comm.LinuxCommand.__init__(self, TestRun.executor, 'ddrescue')
- self.source_path = None
- self.destination_path = None
- self.param_name_prefix = "--"
-
- def source(self, value):
- self.source_path = value
- return self
-
- def destination(self, value):
- self.destination_path = value
- return self
-
- def reverse(self):
- return self.set_flags("reverse")
-
- def synchronous(self):
- return self.set_flags("synchronous")
-
- def direct(self):
- return self.set_flags("direct")
-
- def force(self):
- return self.set_flags("force")
-
- def block_size(self, value: size.Size):
- return self.set_param('sector-size', int(value.get_value()))
-
- def size(self, value: size.Size):
- return self.set_param('size', int(value.get_value()))
-
- def __str__(self):
- command = linux_comm.LinuxCommand.__str__(self)
- command += f" {self.source_path} {self.destination_path}"
- return command
diff --git a/test/functional/test-framework/test_tools/device_mapper.py b/test/functional/test-framework/test_tools/device_mapper.py
deleted file mode 100644
index ede38df..0000000
--- a/test/functional/test-framework/test_tools/device_mapper.py
+++ /dev/null
@@ -1,329 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from enum import Enum
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_utils.disk_finder import resolve_to_by_id_link
-from test_utils.linux_command import LinuxCommand
-from test_utils.size import Size, Unit
-
-
-class DmTarget(Enum):
- # Fill argument types for other targets if you need them
- LINEAR = (str, int)
- STRIPED = (int, int, list)
- ERROR = ()
- ZERO = ()
- CRYPT = ()
- DELAY = (str, int, int, str, int, int)
- FLAKEY = (str, int, int, int)
- MIRROR = ()
- MULTIPATH = ()
- RAID = ()
- SNAPSHOT = ()
-
- def __str__(self):
- return self.name.lower()
-
-
-class DmTable:
- class TableEntry:
- pass
-
-
-class DmTable:
- class TableEntry:
- def __init__(self, offset: int, length: int, target: DmTarget, *params):
- self.offset = int(offset)
- self.length = int(length)
- self.target = DmTarget(target)
- self.params = list(params)
- self.validate()
-
- def validate(self):
- if self.target.value:
- for i in range(len(self.params)):
- try:
- self.params[i] = self.target.value[i](self.params[i])
- except IndexError:
- raise ValueError("invalid dm target parameter")
-
- def __str__(self):
- ret = f"{self.offset} {self.length} {self.target}"
- for param in self.params:
- ret += f" {param}"
-
- return ret
-
- def __init__(self):
- self.table = []
-
- @classmethod
- def uniform_error_table(
- cls, start_lba: int, stop_lba: int, num_error_zones: int, error_zone_size: Size
- ):
- table = cls()
- increment = (stop_lba - start_lba) // num_error_zones
-
- for zone_start in range(start_lba, stop_lba, increment):
- table.add_entry(
- DmTable.TableEntry(
- zone_start,
- error_zone_size.get_value(Unit.Blocks512),
- DmTarget.ERROR,
- )
- )
-
- return table
-
- @classmethod
- def passthrough_table(cls, device: Device):
- table = cls()
-
- table.add_entry(
- DmTable.TableEntry(
- 0,
- device.size.get_value(Unit.Blocks512),
- DmTarget.LINEAR,
- device.path,
- 0,
- )
- )
-
- return table
-
- @classmethod
- def error_table(cls, offset: int, size: Size):
- table = cls()
-
- table.add_entry(
- DmTable.TableEntry(offset, size.get_value(Unit.Blocks512), DmTarget.ERROR)
- )
-
- return table
-
- def fill_gaps(self, device: Device, fill_end=True):
- gaps = self.get_gaps()
-
- for gap in gaps[:-1]:
- self.add_entry(
- DmTable.TableEntry(
- gap[0], gap[1], DmTarget.LINEAR, device.path, int(gap[0])
- )
- )
-
- table_end = gaps[-1][0]
-
- if fill_end and (Size(table_end, Unit.Blocks512) < device.size):
- self.add_entry(
- DmTable.TableEntry(
- table_end,
- device.size.get_value(Unit.Blocks512) - table_end,
- DmTarget.LINEAR,
- device.path,
- table_end,
- )
- )
-
- return self
-
- def add_entry(self, entry: DmTable.TableEntry):
- self.table.append(entry)
- return self
-
- def get_gaps(self):
- if not self.table:
- return [(0, -1)]
-
- gaps = []
-
- self.table.sort(key=lambda entry: entry.offset)
-
- if self.table[0].offset != 0:
- gaps.append((0, self.table[0].offset))
-
- for e1, e2 in zip(self.table, self.table[1:]):
- if e1.offset + e1.length != e2.offset:
- gaps.append(
- (e1.offset + e1.length, e2.offset - (e1.offset + e1.length))
- )
-
- if len(self.table) > 1:
- gaps.append((e2.offset + e2.length, -1))
- else:
- gaps.append((self.table[0].offset + self.table[0].length, -1))
-
- return gaps
-
- def validate(self):
- self.table.sort(key=lambda entry: entry.offset)
-
- if self.table[0].offset != 0:
- raise ValueError(f"dm table should start at LBA 0: {self.table[0]}")
-
- for e1, e2 in zip(self.table, self.table[1:]):
- if e1.offset + e1.length != e2.offset:
- raise ValueError(
- f"dm table should not have any holes or overlaps: {e1} -> {e2}"
- )
-
- def get_size(self):
- self.table.sort(key=lambda entry: entry.offset)
-
- return Size(self.table[-1].offset + self.table[-1].length, Unit.Blocks512)
-
- def __str__(self):
- output = ""
-
- for entry in self.table:
- output += f"{entry}\n"
-
- return output
-
-
-class DeviceMapper(LinuxCommand):
- @classmethod
- def remove_all(cls, force=True):
- TestRun.LOGGER.info("Removing all device mapper devices")
-
- cmd = "dmsetup remove_all"
- if force:
- cmd += " --force"
-
- return TestRun.executor.run_expect_success(cmd)
-
- def __init__(self, name: str):
- LinuxCommand.__init__(self, TestRun.executor, "dmsetup")
- self.name = name
-
- @staticmethod
- def wrap_table(table: DmTable):
- return f"<< ENDHERE\n{str(table)}ENDHERE\n"
-
- def get_path(self):
- return f"/dev/mapper/{self.name}"
-
- def clear(self):
- return TestRun.executor.run_expect_success(f"{self.command_name} clear {self.name}")
-
- def create(self, table: DmTable):
- try:
- table.validate()
- except ValueError:
- for entry in table.table:
- TestRun.LOGGER.error(f"{entry}")
- raise
-
- TestRun.LOGGER.info(f"Creating device mapper device '{self.name}'")
-
- for entry in table.table:
- TestRun.LOGGER.debug(f"{entry}")
-
- return TestRun.executor.run_expect_success(
- f"{self.command_name} create {self.name} {self.wrap_table(table)}"
- )
-
- def remove(self):
- TestRun.LOGGER.info(f"Removing device mapper device '{self.name}'")
-
- return TestRun.executor.run_expect_success(f"{self.command_name} remove {self.name}")
-
- def suspend(self):
- TestRun.LOGGER.info(f"Suspending device mapper device '{self.name}'")
- return TestRun.executor.run_expect_success(f"{self.command_name} suspend {self.name}")
-
- def resume(self):
- TestRun.LOGGER.info(f"Resuming device mapper device '{self.name}'")
- return TestRun.executor.run_expect_success(f"{self.command_name} resume {self.name}")
-
- def reload(self, table: DmTable):
- table.validate()
- TestRun.LOGGER.info(f"Reloading table for device mapper device '{self.name}'")
-
- for entry in table.table:
- TestRun.LOGGER.debug(f"{entry}")
-
- return TestRun.executor.run_expect_success(
- f"{self.command_name} reload {self.name} {self.wrap_table(table)}"
- )
-
-
-class ErrorDevice(Device):
- def __init__(self, name: str, base_device: Device, table: DmTable = None):
- self.device = base_device
- self.mapper = DeviceMapper(name)
- self.name = name
- self.table = DmTable.passthrough_table(base_device) if not table else table
- self.active = False
- self.start()
- self.path = resolve_to_by_id_link(self.mapper.get_path().replace('/dev/', ''))
-
- @property
- def system_path(self):
- if self.active:
- output = TestRun.executor.run_expect_success(f"realpath {self.mapper.get_path()}")
-
- return output.stdout
-
- return None
-
- @property
- def size(self):
- if self.active:
- return self.table.get_size()
-
- return None
-
- def start(self):
- self.mapper.create(self.table)
- self.active = True
-
- def stop(self):
- self.mapper.remove()
- self.active = False
-
- def change_table(self, table: DmTable, permanent=True):
- if self.active:
- self.mapper.suspend()
-
- self.mapper.reload(table)
-
- self.mapper.resume()
-
- if permanent:
- self.table = table
-
- def suspend_errors(self):
- empty_table = DmTable.passthrough_table(self.device)
- TestRun.LOGGER.info(f"Suspending issuing errors for error device '{self.name}'")
-
- self.change_table(empty_table, False)
-
- def resume_errors(self):
- TestRun.LOGGER.info(f"Resuming issuing errors for error device '{self.name}'")
-
- self.change_table(self.table, False)
-
- def suspend(self):
- if not self.active:
- TestRun.LOGGER.warning(
- f"cannot suspend error device '{self.name}'! It's already running"
- )
-
- self.mapper.suspend()
-
- self.active = False
-
- def resume(self):
- if self.active:
- TestRun.LOGGER.warning(
- f"cannot resume error device '{self.name}'! It's already running"
- )
-
- self.mapper.resume()
-
- self.active = True
diff --git a/test/functional/test-framework/test_tools/disk_utils.py b/test/functional/test-framework/test_tools/disk_utils.py
deleted file mode 100644
index 38ac3a7..0000000
--- a/test/functional/test-framework/test_tools/disk_utils.py
+++ /dev/null
@@ -1,397 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import posixpath
-import re
-import time
-from enum import Enum
-
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_tools.dd import Dd
-from test_tools.fs_utils import readlink, parse_ls_output, ls
-from test_utils.output import CmdException
-from test_utils.size import Size, Unit
-
-SECTOR_SIZE = 512
-
-
-class Filesystem(Enum):
- xfs = 0
- ext3 = 1
- ext4 = 2
-
-
-class PartitionTable(Enum):
- msdos = 0
- gpt = 1
-
-
-class PartitionType(Enum):
- efi = 0
- primary = 1
- extended = 2
- logical = 3
- lvm = 4
- msr = 5
- swap = 6
- standard = 7
- unknown = 8
-
-
-def create_filesystem(device, filesystem: Filesystem, force=True, blocksize=None):
- TestRun.LOGGER.info(
- f"Creating filesystem ({filesystem.name}) on device: {device.path}")
- force_param = ' -f ' if filesystem == Filesystem.xfs else ' -F '
- force_param = force_param if force else ''
- block_size_param = f' -b size={blocksize}' if filesystem == Filesystem.xfs \
- else f' -b {blocksize}'
- block_size_param = block_size_param if blocksize else ''
- cmd = f'mkfs.{filesystem.name} {force_param} {device.path} {block_size_param}'
- cmd = re.sub(' +', ' ', cmd)
- TestRun.executor.run_expect_success(cmd)
- TestRun.LOGGER.info(
- f"Successfully created filesystem on device: {device.path}")
-
-
-def create_partition_table(device, partition_table_type: PartitionTable = PartitionTable.gpt):
- TestRun.LOGGER.info(
- f"Creating partition table ({partition_table_type.name}) for device: {device.path}")
- cmd = f'parted --script {device.path} mklabel {partition_table_type.name}'
- TestRun.executor.run_expect_success(cmd)
- device.partition_table = partition_table_type
- TestRun.LOGGER.info(
- f"Successfully created {partition_table_type.name} "
- f"partition table on device: {device.path}")
-
-
-def get_partition_path(parent_dev, number):
- # TODO: change this to be less specific hw dependent (kernel)
- if "dev/cas" not in parent_dev:
- id_separator = '-part'
- else:
- id_separator = 'p' # "cas1-1p1"
- return f'{parent_dev}{id_separator}{number}'
-
-
-def remove_parition(device, part_number):
- TestRun.LOGGER.info(f"Removing part {part_number} from {device.path}")
- cmd = f'parted --script {device.path} rm {part_number}'
- output = TestRun.executor.run(cmd)
-
- if output.exit_code != 0:
- TestRun.executor.run_expect_success("partprobe")
-
-
-def create_partition(
- device,
- part_size,
- part_number,
- part_type: PartitionType = PartitionType.primary,
- unit=Unit.MebiByte,
- aligned: bool = True):
- TestRun.LOGGER.info(
- f"Creating {part_type.name} partition on device: {device.path}")
-
- begin = get_first_partition_offset(device, aligned)
- for part in device.partitions:
- begin += part.size
- if part.type == PartitionType.logical:
- begin += Size(1, Unit.MebiByte if not aligned else device.block_size)
-
- if part_type == PartitionType.logical:
- begin += Size(1, Unit.MebiByte if not aligned else device.block_size)
-
- if part_size != Size.zero():
- end = (begin + part_size)
- end_cmd = f'{end.get_value(unit)}{unit_to_string(unit)}'
- else:
- end_cmd = '100%'
-
- cmd = f'parted --script {device.path} mkpart ' \
- f'{part_type.name} ' \
- f'{begin.get_value(unit)}{unit_to_string(unit)} ' \
- f'{end_cmd}'
- output = TestRun.executor.run(cmd)
-
- if output.exit_code != 0:
- TestRun.executor.run_expect_success("partprobe")
-
- TestRun.executor.run_expect_success("udevadm settle")
- if not check_partition_after_create(
- part_size,
- part_number,
- device.path,
- part_type,
- aligned):
- raise Exception("Could not create partition!")
-
- if part_type != PartitionType.extended:
- from storage_devices.partition import Partition
- new_part = Partition(device,
- part_type,
- part_number,
- begin,
- end if type(end) is Size else device.size)
- dd = Dd().input("/dev/zero") \
- .output(new_part.path) \
- .count(1) \
- .block_size(Size(1, Unit.Blocks4096)) \
- .oflag("direct")
- dd.run()
- device.partitions.append(new_part)
-
- TestRun.LOGGER.info(f"Successfully created {part_type.name} partition on {device.path}")
-
-
-def available_disk_size(device):
- dev = f"/dev/{device.get_device_id()}"
- # get number of device's sectors
- disk_sectors = int(TestRun.executor.run(f"fdisk -l {dev} | grep {dev} | grep sectors "
- f"| awk '{{print $7 }}' ").stdout)
- # get last occupied sector
- last_occupied_sector = int(TestRun.executor.run(f"fdisk -l {dev} | grep {dev} "
- f"| awk '{{print $3 }}' | tail -1").stdout)
- available_disk_sectors = disk_sectors - last_occupied_sector
- return Size(available_disk_sectors, Unit(get_block_size(device)))
-
-
-def create_partitions(device, sizes: [], partition_table_type=PartitionTable.gpt):
- create_partition_table(device, partition_table_type)
- partition_type = PartitionType.primary
- partition_number_offset = 0
- msdos_part_max_size = Size(2, Unit.TeraByte)
-
- for s in sizes:
- size = Size(
- s.get_value(device.block_size) - device.block_size.value, device.block_size)
- if partition_table_type == PartitionTable.msdos and \
- len(sizes) > 4 and len(device.partitions) == 3:
- if available_disk_size(device) > msdos_part_max_size:
- part_size = msdos_part_max_size
- else:
- part_size = Size.zero()
- create_partition(device,
- part_size,
- 4,
- PartitionType.extended)
- partition_type = PartitionType.logical
- partition_number_offset = 1
-
- partition_number = len(device.partitions) + 1 + partition_number_offset
- create_partition(device,
- size,
- partition_number,
- partition_type,
- Unit.MebiByte,
- True)
-
-
-def get_block_size(device):
- try:
- block_size = float(TestRun.executor.run(
- f"cat {get_sysfs_path(device)}/queue/hw_sector_size").stdout)
- except ValueError:
- block_size = Unit.Blocks512.value
- return block_size
-
-
-def get_size(device):
- output = TestRun.executor.run_expect_success(f"cat {get_sysfs_path(device)}/size")
- blocks_count = int(output.stdout)
- return blocks_count * SECTOR_SIZE
-
-
-def get_sysfs_path(device):
- sysfs_path = f"/sys/class/block/{device}"
- if TestRun.executor.run(f"test -d {sysfs_path}").exit_code != 0:
- sysfs_path = f"/sys/block/{device}"
- return sysfs_path
-
-
-def get_pci_address(device):
- pci_address = TestRun.executor.run(f"cat /sys/block/{device}/device/address").stdout
- return pci_address
-
-
-def check_partition_after_create(size, part_number, parent_dev_path, part_type, aligned):
- partition_path = get_partition_path(parent_dev_path, part_number)
- if "dev/cas" not in partition_path:
- cmd = f"find {partition_path} -type l"
- else:
- cmd = f"find {partition_path}"
- output = TestRun.executor.run_expect_success(cmd).stdout
- if partition_path not in output:
- TestRun.LOGGER.info(
- "Partition created, but could not find it in system, trying 'hdparm -z'")
- TestRun.executor.run_expect_success(f"hdparm -z {parent_dev_path}")
- output_after_hdparm = TestRun.executor.run_expect_success(
- f"parted --script {parent_dev_path} print").stdout
- TestRun.LOGGER.info(output_after_hdparm)
-
- counter = 0
- while partition_path not in output and counter < 10:
- time.sleep(2)
- output = TestRun.executor.run(cmd).stdout
- counter += 1
-
- if len(output.split('\n')) > 1 or partition_path not in output:
- return False
-
- if aligned and part_type != PartitionType.extended \
- and size.get_value(Unit.Byte) % Unit.Blocks4096.value != 0:
- TestRun.LOGGER.warning(
- f"Partition {partition_path} is not 4k aligned: {size.get_value(Unit.KibiByte)}KiB")
-
- partition_size = get_size(readlink(partition_path).split('/')[-1])
- if part_type == PartitionType.extended or \
- partition_size == size.get_value(Unit.Byte):
- return True
-
- TestRun.LOGGER.warning(
- f"Partition size {partition_size} does not match expected {size.get_value(Unit.Byte)} size."
- )
- return True
-
-
-def get_first_partition_offset(device, aligned: bool):
- if aligned:
- return Size(1, Unit.MebiByte)
- # 33 sectors are reserved for the backup GPT
- return Size(34, Unit(device.blocksize)) \
- if device.partition_table == PartitionTable.gpt else Size(1, device.blocksize)
-
-
-def remove_partitions(device):
- from test_utils.os_utils import Udev
- if device.is_mounted():
- device.unmount()
-
- for partition in device.partitions:
- unmount(partition)
-
- TestRun.LOGGER.info(f"Removing partitions from device: {device.path} "
- f"({device.get_device_id()}).")
- device.wipe_filesystem()
- Udev.trigger()
- Udev.settle()
- output = TestRun.executor.run(f"ls {device.path}* -1")
- if len(output.stdout.split('\n')) > 1:
- TestRun.LOGGER.error(f"Could not remove partitions from device {device.path}")
- return False
- return True
-
-
-def mount(device, mount_point, options: [str] = None):
- if not fs_utils.check_if_directory_exists(mount_point):
- fs_utils.create_directory(mount_point, True)
- TestRun.LOGGER.info(f"Mounting device {device.path} ({device.get_device_id()}) "
- f"to {mount_point}.")
- cmd = f"mount {device.path} {mount_point}"
- if options:
- cmd = f"{cmd} -o {','.join(options)}"
- output = TestRun.executor.run(cmd)
- if output.exit_code != 0:
- raise Exception(f"Failed to mount {device.path} to {mount_point}")
- device.mount_point = mount_point
-
-
-def unmount(device):
- TestRun.LOGGER.info(f"Unmounting device {device.path} ({device.get_device_id()}).")
- if device.mount_point is not None:
- output = TestRun.executor.run(f"umount {device.mount_point}")
- if output.exit_code != 0:
- TestRun.LOGGER.error("Could not unmount device.")
- return False
- return True
- else:
- TestRun.LOGGER.info("Device is not mounted.")
- return True
-
-
-def unit_to_string(unit):
- unit_string = {
- Unit.Byte: 'B',
- Unit.Blocks512: 's',
- Unit.Blocks4096: 's',
- Unit.KibiByte: 'KiB',
- Unit.MebiByte: 'MiB',
- Unit.GibiByte: 'GiB',
- Unit.TebiByte: 'TiB',
- Unit.KiloByte: 'kB',
- Unit.MegaByte: 'MB',
- Unit.GigaByte: 'GB',
- Unit.TeraByte: 'TB'
- }
- return unit_string.get(unit, "Invalid unit.")
-
-
-def wipe_filesystem(device, force=True):
- TestRun.LOGGER.info(f"Erasing the device: {device.path}")
- force_param = ' -f' if force else ''
- cmd = f'wipefs -a{force_param} {device.path}'
- TestRun.executor.run_expect_success(cmd)
- TestRun.LOGGER.info(
- f"Successfully wiped device: {device.path}")
-
-
-def check_if_device_supports_trim(device):
- if device.get_device_id().startswith("nvme"):
- return True
- command_output = TestRun.executor.run(
- f'hdparm -I {device.path} | grep "TRIM supported"')
- return command_output.exit_code == 0
-
-
-def get_device_filesystem_type(device_id):
- cmd = f'lsblk -l -o NAME,FSTYPE | sort | uniq | grep "{device_id} "'
- try:
- stdout = TestRun.executor.run_expect_success(cmd).stdout
- except CmdException:
- # unusual devices might not be listed in output (i.e. RAID containers)
- if TestRun.executor.run(f"test -b /dev/{device_id}").exit_code != 0:
- raise
- else:
- return None
- split_stdout = stdout.strip().split()
- if len(split_stdout) <= 1:
- return None
- else:
- try:
- return Filesystem[split_stdout[1]]
- except KeyError:
- TestRun.LOGGER.warning(f"Unrecognized filesystem: {split_stdout[1]}")
- return None
-
-
-def _is_by_id_path(path: str):
- """check if given path already is proper by-id path"""
- dev_by_id_dir = "/dev/disk/by-id"
- by_id_paths = parse_ls_output(ls(dev_by_id_dir), dev_by_id_dir)
- return path in [posixpath.join(dev_by_id_dir, id_path.full_path) for id_path in by_id_paths]
-
-
-def _is_dev_path_whitelisted(path: str):
- """check if given path is whitelisted"""
- whitelisted_paths = [r"cas\d+-\d+", r"/dev/dm-\d+"]
-
- for whitelisted_path in whitelisted_paths:
- if re.search(whitelisted_path, path) is not None:
- return True
-
- return False
-
-
-def validate_dev_path(path: str):
- if not posixpath.isabs(path):
- raise ValueError(f'Given path "{path}" is not absolute.')
-
- if _is_dev_path_whitelisted(path):
- return path
-
- if _is_by_id_path(path):
- return path
-
- raise ValueError(f'By-id device link {path} is broken.')
diff --git a/test/functional/test-framework/test_tools/drbdadm.py b/test/functional/test-framework/test_tools/drbdadm.py
deleted file mode 100644
index 8213e91..0000000
--- a/test/functional/test-framework/test_tools/drbdadm.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause-Clear
-#
-
-from core.test_run import TestRun
-
-
-class Drbdadm:
- # create metadata for resource
- @staticmethod
- def create_metadata(resource_name: str, force: bool):
- cmd = "drbdadm create-md" + (" --force" if force else "") + f" {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- # enable resource
- @staticmethod
- def up(resource_name: str):
- cmd = f"drbdadm up {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- # disable resource
- @staticmethod
- def down_all():
- cmd = f"drbdadm down all"
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def down(resource_name):
- cmd = f"drbdadm down {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- # promote resource to primary
- @staticmethod
- def set_node_primary(resource_name: str, force=False):
- cmd = f"drbdadm primary {resource_name}"
- cmd += " --force" if force else ""
- return TestRun.executor.run_expect_success(cmd)
-
- # demote resource to secondary
- @staticmethod
- def set_node_secondary(resource_name: str):
- cmd = f"drbdadm secondary {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- # check status for all or for specified resource
- @staticmethod
- def get_status(resource_name: str = ""):
- cmd = f"drbdadm status {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def in_sync(resource_name: str):
- cmd = f"drbdadm status {resource_name} | grep Inconsistent"
- return TestRun.executor.run(cmd).exit_code == 1
-
- # wait sync
- @staticmethod
- def wait_for_sync(resource_name: str = ""):
- # ssh connection might timeout in case on long sync
- cmd = f"drbdadm wait-sync {resource_name}"
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def dump_config(resource_name: str):
- cmd = f"drbdadm dump {resource_name}"
- return TestRun.executor.run(cmd)
diff --git a/test/functional/test-framework/test_tools/fio/__init__.py b/test/functional/test-framework/test_tools/fio/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/test_tools/fio/fio.py b/test/functional/test-framework/test_tools/fio/fio.py
deleted file mode 100644
index 963ae0e..0000000
--- a/test/functional/test-framework/test_tools/fio/fio.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import datetime
-import uuid
-
-import test_tools.fio.fio_param
-import test_tools.fs_utils
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_utils import os_utils
-
-
-class Fio:
- def __init__(self, executor_obj=None):
- self.fio_version = "fio-3.30"
- self.default_run_time = datetime.timedelta(hours=1)
- self.jobs = []
- self.executor = executor_obj if executor_obj is not None else TestRun.executor
- self.base_cmd_parameters: test_tools.fio.fio_param.FioParam = None
- self.global_cmd_parameters: test_tools.fio.fio_param.FioParam = None
-
- def create_command(self, output_type=test_tools.fio.fio_param.FioOutput.json):
- self.base_cmd_parameters = test_tools.fio.fio_param.FioParamCmd(self, self.executor)
- self.global_cmd_parameters = test_tools.fio.fio_param.FioParamConfig(self, self.executor)
-
- self.fio_file = f'fio_run_{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}_{uuid.uuid4().hex}'
- self.base_cmd_parameters\
- .set_param('eta', 'always')\
- .set_param('output-format', output_type.value)\
- .set_param('output', self.fio_file)
-
- self.global_cmd_parameters.set_flags('group_reporting')
-
- return self.global_cmd_parameters
-
- def is_installed(self):
- return self.executor.run("fio --version").stdout.strip() == self.fio_version
-
- def install(self):
- fio_url = f"http://brick.kernel.dk/snaps/{self.fio_version}.tar.bz2"
- fio_package = os_utils.download_file(fio_url)
- fs_utils.uncompress_archive(fio_package)
- TestRun.executor.run_expect_success(f"cd {fio_package.parent_dir}/{self.fio_version}"
- f" && ./configure && make -j && make install")
-
- def calculate_timeout(self):
- if "time_based" not in self.global_cmd_parameters.command_flags:
- return self.default_run_time
-
- total_time = self.global_cmd_parameters.get_parameter_value("runtime")
- if len(total_time) != 1:
- raise ValueError("Wrong fio 'runtime' parameter configuration")
- total_time = int(total_time[0])
- ramp_time = self.global_cmd_parameters.get_parameter_value("ramp_time")
- if ramp_time is not None:
- if len(ramp_time) != 1:
- raise ValueError("Wrong fio 'ramp_time' parameter configuration")
- ramp_time = int(ramp_time[0])
- total_time += ramp_time
- return datetime.timedelta(seconds=total_time)
-
- def run(self, timeout: datetime.timedelta = None):
- if timeout is None:
- timeout = self.calculate_timeout()
-
- self.prepare_run()
- return self.executor.run(str(self), timeout)
-
- def run_in_background(self):
- self.prepare_run()
- return self.executor.run_in_background(str(self))
-
- def prepare_run(self):
- if not self.is_installed():
- self.install()
-
- if len(self.jobs) > 0:
- self.executor.run(f"{str(self)}-showcmd -")
- TestRun.LOGGER.info(self.executor.run(f"cat {self.fio_file}").stdout)
- TestRun.LOGGER.info(str(self))
-
- def execution_cmd_parameters(self):
- if len(self.jobs) > 0:
- separator = "\n\n"
- return f"{str(self.global_cmd_parameters)}\n" \
- f"{separator.join(str(job) for job in self.jobs)}"
- else:
- return str(self.global_cmd_parameters)
-
- def __str__(self):
- if len(self.jobs) > 0:
- command = f"echo '{self.execution_cmd_parameters()}' |" \
- f" {str(self.base_cmd_parameters)} -"
- else:
- fio_parameters = test_tools.fio.fio_param.FioParamCmd(self, self.executor)
- fio_parameters.command_env_var.update(self.base_cmd_parameters.command_env_var)
- fio_parameters.command_param.update(self.base_cmd_parameters.command_param)
- fio_parameters.command_param.update(self.global_cmd_parameters.command_param)
- fio_parameters.command_flags.extend(self.global_cmd_parameters.command_flags)
- fio_parameters.set_param('name', 'fio')
- command = str(fio_parameters)
- return command
diff --git a/test/functional/test-framework/test_tools/fio/fio_param.py b/test/functional/test-framework/test_tools/fio/fio_param.py
deleted file mode 100644
index 8db911b..0000000
--- a/test/functional/test-framework/test_tools/fio/fio_param.py
+++ /dev/null
@@ -1,388 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import datetime
-import json
-import secrets
-from enum import Enum
-from types import SimpleNamespace as Namespace
-
-from connection.base_executor import BaseExecutor
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_tools.fio.fio_result import FioResult
-from test_utils.linux_command import LinuxCommand
-from test_utils.size import Size
-
-
-class CpusAllowedPolicy(Enum):
- shared = 0,
- split = 1
-
-
-class ErrorFilter(Enum):
- none = 0,
- read = 1,
- write = 2,
- io = 3,
- verify = 4,
- all = 5
-
-
-class FioOutput(Enum):
- normal = 'normal'
- terse = 'terse'
- json = 'json'
- jsonplus = 'json+'
-
-
-class IoEngine(Enum):
- # Basic read or write I/O. fseek is used to position the I/O location.
- sync = 0,
- # Linux native asynchronous I/O.
- libaio = 1,
- # Basic pread or pwrite I/O.
- psync = 2,
- # Basic readv or writev I/O.
- # Will emulate queuing by coalescing adjacent IOs into a single submission.
- vsync = 3,
- # Basic preadv or pwritev I/O.
- pvsync = 4,
- # POSIX asynchronous I/O using aio_read and aio_write.
- posixaio = 5,
- # File is memory mapped with mmap and data copied using memcpy.
- mmap = 6,
- # RADOS Block Device
- rbd = 7,
- # SPDK Block Device
- spdk_bdev = 8
-
-
-class ReadWrite(Enum):
- randread = 0,
- randrw = 1,
- randwrite = 2,
- read = 3,
- readwrite = 4,
- write = 5,
- trim = 6,
- randtrim = 7,
- trimwrite = 8
-
-
-class VerifyMethod(Enum):
- # Use an md5 sum of the data area and store it in the header of each block.
- md5 = 0,
- # Use an experimental crc64 sum of the data area and store it in the header of each block.
- crc64 = 1,
- # Use optimized sha1 as the checksum function.
- sha1 = 2,
- # Verify a strict pattern.
- # Normally fio includes a header with some basic information and a checksum, but if this
- # option is set, only the specific pattern set with verify_pattern is verified.
- pattern = 3,
- # Write extra information about each I/O (timestamp, block number, etc.).
- # The block number is verified.
- meta = 4
-
-
-class RandomGenerator(Enum):
- tausworthe = 0,
- lfsr = 1,
- tausworthe64 = 2
-
-
-class FioParam(LinuxCommand):
- def __init__(self, fio, command_executor: BaseExecutor, command_name):
- LinuxCommand.__init__(self, command_executor, command_name)
- self.verification_pattern = ''
- self.fio = fio
-
- def get_verification_pattern(self):
- if not self.verification_pattern:
- self.verification_pattern = f'0x{secrets.token_hex(32)}'
- return self.verification_pattern
-
- def allow_mounted_write(self, value: bool = True):
- return self.set_param('allow_mounted_write', int(value))
-
- # example: "bs=8k,32k" => 8k for reads, 32k for writes and trims
- def block_size(self, *sizes: Size):
- return self.set_param('blocksize', *[int(size) for size in sizes])
-
- def blocksize_range(self, ranges):
- value = []
- for bs_range in ranges:
- str_range = str(int(bs_range[0])) + '-' + str(int(bs_range[1]))
- value.append(str_range)
- return self.set_param('blocksize_range', ",".join(value))
-
- def bs_split(self, value):
- return self.set_param('bssplit', value)
-
- def buffer_pattern(self, pattern):
- return self.set_param('buffer_pattern', pattern)
-
- def continue_on_error(self, value: ErrorFilter):
- return self.set_param('continue_on_error', value.name)
-
- def cpus_allowed(self, value):
- return self.set_param('cpus_allowed', ",".join(value))
-
- def cpus_allowed_policy(self, value: CpusAllowedPolicy):
- return self.set_param('cpus_allowed_policy', value.name)
-
- def direct(self, value: bool = True):
- if 'buffered' in self.command_param:
- self.remove_param('buffered')
- return self.set_param('direct', int(value))
-
- def directory(self, directory):
- return self.set_param('directory', directory)
-
- def do_verify(self, value: bool = True):
- return self.set_param('do_verify', int(value))
-
- def exit_all_on_error(self, value: bool = True):
- return self.set_flags('exitall_on_error') if value \
- else self.remove_flag('exitall_on_error')
-
- def group_reporting(self, value: bool = True):
- return self.set_flags('group_reporting') if value else self.remove_flag('group_reporting')
-
- def file_name(self, path):
- return self.set_param('filename', path)
-
- def file_size(self, size: Size):
- return self.set_param('filesize', int(size))
-
- def file_size_range(self, ranges):
- value = []
- for bs_range in ranges:
- str_range = str(int(bs_range[0])) + '-' + str(int(bs_range[1]))
- value.append(str_range)
- return self.set_param('filesize', ",".join(value))
-
- def fsync(self, value: int):
- return self.set_param('fsync', value)
-
- def ignore_errors(self, read_errors, write_errors, verify_errors):
- separator = ':'
- return self.set_param(
- 'ignore_error',
- separator.join(str(err) for err in read_errors),
- separator.join(str(err) for err in write_errors),
- separator.join(str(err) for err in verify_errors))
-
- def io_depth(self, value: int):
- if value != 1:
- if 'ioengine' in self.command_param and \
- self.command_param['ioengine'] == 'sync':
- TestRun.LOGGER.warning("Setting iodepth will have no effect with "
- "'ioengine=sync' setting")
- return self.set_param('iodepth', value)
-
- def io_engine(self, value: IoEngine):
- if value == IoEngine.sync:
- if 'iodepth' in self.command_param and self.command_param['iodepth'] != 1:
- TestRun.LOGGER.warning("Setting 'ioengine=sync' will cause iodepth setting "
- "to be ignored")
- return self.set_param('ioengine', value.name)
-
- def io_size(self, value: Size):
- return self.set_param('io_size', int(value.get_value()))
-
- def loops(self, value: int):
- return self.set_param('loops', value)
-
- def no_random_map(self, value: bool = True):
- if 'verify' in self.command_param:
- raise ValueError("'NoRandomMap' parameter is mutually exclusive with verify")
- if value:
- return self.set_flags('norandommap')
- else:
- return self.remove_flag('norandommap')
-
- def nr_files(self, value: int):
- return self.set_param('nrfiles', value)
-
- def num_ios(self, value: int):
- return self.set_param('number_ios', value)
-
- def num_jobs(self, value: int):
- return self.set_param('numjobs', value)
-
- def offset(self, value: Size):
- return self.set_param('offset', int(value.get_value()))
-
- def offset_increment(self, value: Size):
- return self.set_param('offset_increment', f"{value.value}{value.unit.get_short_name()}")
-
- def percentage_random(self, value: int):
- if value <= 100:
- return self.set_param('percentage_random', value)
- raise ValueError("Argument out of range. Should be 0-100.")
-
- def pool(self, value):
- return self.set_param('pool', value)
-
- def ramp_time(self, value: datetime.timedelta):
- return self.set_param('ramp_time', int(value.total_seconds()))
-
- def random_distribution(self, value):
- return self.set_param('random_distribution', value)
-
- def rand_repeat(self, value: int):
- return self.set_param('randrepeat', value)
-
- def rand_seed(self, value: int):
- return self.set_param('randseed', value)
-
- def read_write(self, rw: ReadWrite):
- return self.set_param('readwrite', rw.name)
-
- def run_time(self, value: datetime.timedelta):
- if value.total_seconds() == 0:
- raise ValueError("Runtime parameter must not be set to 0.")
- return self.set_param('runtime', int(value.total_seconds()))
-
- def serialize_overlap(self, value: bool = True):
- return self.set_param('serialize_overlap', int(value))
-
- def size(self, value: Size):
- return self.set_param('size', int(value.get_value()))
-
- def stonewall(self, value: bool = True):
- return self.set_flags('stonewall') if value else self.remove_param('stonewall')
-
- def sync(self, value: bool = True):
- return self.set_param('sync', int(value))
-
- def time_based(self, value: bool = True):
- return self.set_flags('time_based') if value else self.remove_flag('time_based')
-
- def thread(self, value: bool = True):
- return self.set_flags('thread') if value else self.remove_param('thread')
-
- def lat_percentiles(self, value: bool):
- return self.set_param('lat_percentiles', int(value))
-
- def scramble_buffers(self, value: bool):
- return self.set_param('scramble_buffers', int(value))
-
- def slat_percentiles(self, value: bool):
- return self.set_param('slat_percentiles', int(value))
-
- def spdk_core_mask(self, value: str):
- return self.set_param('spdk_core_mask', value)
-
- def spdk_json_conf(self, path):
- return self.set_param('spdk_json_conf', path)
-
- def clat_percentiles(self, value: bool):
- return self.set_param('clat_percentiles', int(value))
-
- def percentile_list(self, value: []):
- val = ':'.join(value) if len(value) > 0 else '100'
- return self.set_param('percentile_list', val)
-
- def verification_with_pattern(self, pattern=None):
- if pattern is not None and pattern != '':
- self.verification_pattern = pattern
- return self.verify(VerifyMethod.pattern) \
- .set_param('verify_pattern', self.get_verification_pattern()) \
- .do_verify()
-
- def verify(self, value: VerifyMethod):
- return self.set_param('verify', value.name)
-
- def create_only(self, value: bool = False):
- return self.set_param('create_only', int(value))
-
- def verify_pattern(self, pattern=None):
- return self.set_param('verify_pattern', pattern or self.get_verification_pattern())
-
- def verify_backlog(self, value: int):
- return self.set_param('verify_backlog', value)
-
- def verify_dump(self, value: bool = True):
- return self.set_param('verify_dump', int(value))
-
- def verify_fatal(self, value: bool = True):
- return self.set_param('verify_fatal', int(value))
-
- def verify_only(self, value: bool = True):
- return self.set_flags('verify_only') if value else self.remove_param('verify_only')
-
- def write_hint(self, value: str):
- return self.set_param('write_hint', value)
-
- def write_percentage(self, value: int):
- if value <= 100:
- return self.set_param('rwmixwrite', value)
- raise ValueError("Argument out of range. Should be 0-100.")
-
- def random_generator(self, value: RandomGenerator):
- return self.set_param('random_generator', value.name)
-
- def target(self, target):
- if isinstance(target, Device):
- return self.file_name(target.path)
- return self.file_name(target)
-
- def add_job(self, job_name=None):
- if not job_name:
- job_name = f'job{len(self.fio.jobs)}'
- new_job = FioParamConfig(self.fio, self.command_executor, f'[{job_name}]')
- self.fio.jobs.append(new_job)
- return new_job
-
- def clear_jobs(self):
- self.fio.jobs = []
-
- return self
-
- def edit_global(self):
- return self.fio.global_cmd_parameters
-
- def run(self, fio_timeout: datetime.timedelta = None):
- if "per_job_logs" in self.fio.global_cmd_parameters.command_param:
- self.fio.global_cmd_parameters.set_param("per_job_logs", '0')
- fio_output = self.fio.run(fio_timeout)
- if fio_output.exit_code != 0:
- raise Exception(f"Exception occurred while trying to execute fio, exit_code:"
- f"{fio_output.exit_code}.\n"
- f"stdout: {fio_output.stdout}\nstderr: {fio_output.stderr}")
- TestRun.executor.run(f"sed -i '/^[[:alnum:]]/d' {self.fio.fio_file}") # Remove warnings
- out = self.command_executor.run_expect_success(f"cat {self.fio.fio_file}").stdout
- return self.get_results(out)
-
- def run_in_background(self):
- if "per_job_logs" in self.fio.global_cmd_parameters.command_param:
- self.fio.global_cmd_parameters.set_param("per_job_logs", '0')
- return self.fio.run_in_background()
-
- @staticmethod
- def get_results(result):
- data = json.loads(result, object_hook=lambda d: Namespace(**d))
- jobs_list = []
- if hasattr(data, 'jobs'):
- jobs = data.jobs
- for job in jobs:
- job_result = FioResult(data, job)
- jobs_list.append(job_result)
- return jobs_list
-
-
-class FioParamCmd(FioParam):
- def __init__(self, fio, command_executor: BaseExecutor, command_name='fio'):
- FioParam.__init__(self, fio, command_executor, command_name)
- self.param_name_prefix = "--"
-
-
-class FioParamConfig(FioParam):
- def __init__(self, fio, command_executor: BaseExecutor, command_name='[global]'):
- FioParam.__init__(self, fio, command_executor, command_name)
- self.param_name_prefix = "\n"
diff --git a/test/functional/test-framework/test_tools/fio/fio_patterns.py b/test/functional/test-framework/test_tools/fio/fio_patterns.py
deleted file mode 100644
index 22ca70b..0000000
--- a/test/functional/test-framework/test_tools/fio/fio_patterns.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import secrets
-from aenum import Enum
-
-
-class Pattern(Enum):
- cyclic = "0x00336699ccffcc996633"
- sequential = "0x" + "".join([f"{i:02x}" for i in range(0, 256)])
- high = "0xaa"
- low = "0x84210"
- zeroes = "0x00"
- ones = "0xff"
- bin_1 = high
- bin_2 = "0x55"
- random = "0x" + secrets.token_hex()
diff --git a/test/functional/test-framework/test_tools/fio/fio_result.py b/test/functional/test-framework/test_tools/fio/fio_result.py
deleted file mode 100644
index 334e977..0000000
--- a/test/functional/test-framework/test_tools/fio/fio_result.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-from test_utils.size import Size, Unit, UnitPerSecond
-from test_utils.time import Time
-
-
-class FioResult:
- def __init__(self, result, job):
- self.result = result
- self.job = job
-
- def __str__(self):
- result_dict = {
- "Total read I/O": self.read_io(),
- "Total read bandwidth ": self.read_bandwidth(),
- "Read bandwidth average ": self.read_bandwidth_average(),
- "Read bandwidth deviation ": self.read_bandwidth_deviation(),
- "Read IOPS": self.read_iops(),
- "Read runtime": self.read_runtime(),
- "Read average completion latency": self.read_completion_latency_average(),
- "Total write I/O": self.write_io(),
- "Total write bandwidth ": self.write_bandwidth(),
- "Write bandwidth average ": self.write_bandwidth_average(),
- "Write bandwidth deviation ": self.write_bandwidth_deviation(),
- "Write IOPS": self.write_iops(),
- "Write runtime": self.write_runtime(),
- "Write average completion latency": self.write_completion_latency_average(),
- }
-
- disks_name = self.disks_name()
- if disks_name:
- result_dict.update({"Disk name": ",".join(disks_name)})
-
- result_dict.update({"Total number of errors": self.total_errors()})
-
- s = ""
- for key in result_dict.keys():
- s += f"{key}: {result_dict[key]}\n"
- return s
-
- def total_errors(self):
- return getattr(self.job, "total_err", 0)
-
- def disks_name(self):
- disks_name = []
- if hasattr(self.result, "disk_util"):
- for disk in self.result.disk_util:
- disks_name.append(disk.name)
- return disks_name
-
- def read_io(self):
- return Size(self.job.read.io_kbytes, Unit.KibiByte)
-
- def read_bandwidth(self):
- return Size(self.job.read.bw, UnitPerSecond(Unit.KibiByte))
-
- def read_bandwidth_average(self):
- return Size(self.job.read.bw_mean, UnitPerSecond(Unit.KibiByte))
-
- def read_bandwidth_deviation(self):
- return Size(self.job.read.bw_dev, UnitPerSecond(Unit.KibiByte))
-
- def read_iops(self):
- return self.job.read.iops
-
- def read_runtime(self):
- return Time(microseconds=self.job.read.runtime)
-
- def read_completion_latency_min(self):
- return Time(nanoseconds=self.job.read.lat_ns.min)
-
- def read_completion_latency_max(self):
- return Time(nanoseconds=self.job.read.lat_ns.max)
-
- def read_completion_latency_average(self):
- return Time(nanoseconds=self.job.read.lat_ns.mean)
-
- def read_completion_latency_percentile(self):
- return self.job.read.lat_ns.percentile.__dict__
-
- def read_requests_number(self):
- return self.result.disk_util[0].read_ios
-
- def write_io(self):
- return Size(self.job.write.io_kbytes, Unit.KibiByte)
-
- def write_bandwidth(self):
- return Size(self.job.write.bw, UnitPerSecond(Unit.KibiByte))
-
- def write_bandwidth_average(self):
- return Size(self.job.write.bw_mean, UnitPerSecond(Unit.KibiByte))
-
- def write_bandwidth_deviation(self):
- return Size(self.job.write.bw_dev, UnitPerSecond(Unit.KibiByte))
-
- def write_iops(self):
- return self.job.write.iops
-
- def write_runtime(self):
- return Time(microseconds=self.job.write.runtime)
-
- def write_completion_latency_average(self):
- return Time(nanoseconds=self.job.write.lat_ns.mean)
-
- def write_completion_latency_min(self):
- return Time(nanoseconds=self.job.write.lat_ns.min)
-
- def write_completion_latency_max(self):
- return Time(nanoseconds=self.job.write.lat_ns.max)
-
- def write_completion_latency_average(self):
- return Time(nanoseconds=self.job.write.lat_ns.mean)
-
- def write_completion_latency_percentile(self):
- return self.job.write.lat_ns.percentile.__dict__
-
- def write_requests_number(self):
- return self.result.disk_util[0].write_ios
-
- def trim_io(self):
- return Size(self.job.trim.io_kbytes, Unit.KibiByte)
-
- def trim_bandwidth(self):
- return Size(self.job.trim.bw, UnitPerSecond(Unit.KibiByte))
-
- def trim_bandwidth_average(self):
- return Size(self.job.trim.bw_mean, UnitPerSecond(Unit.KibiByte))
-
- def trim_bandwidth_deviation(self):
- return Size(self.job.trim.bw_dev, UnitPerSecond(Unit.KibiByte))
-
- def trim_iops(self):
- return self.job.trim.iops
-
- def trim_runtime(self):
- return Time(microseconds=self.job.trim.runtime)
-
- def trim_completion_latency_average(self):
- return Time(nanoseconds=self.job.trim.lat_ns.mean)
-
- def trim_completion_latency_min(self):
- return Time(nanoseconds=self.job.trim.lat_ns.min)
-
- def trim_completion_latency_max(self):
- return Time(nanoseconds=self.job.trim.lat_ns.max)
-
- def trim_completion_latency_average(self):
- return Time(nanoseconds=self.job.trim.lat_ns.mean)
-
- def trim_completion_latency_percentile(self):
- return self.job.trim.lat_ns.percentile.__dict__
-
- @staticmethod
- def result_list_to_dict(results):
- result_dict = {}
-
- for result in results:
- result_dict[result.job.jobname] = result.job
-
- return result_dict
diff --git a/test/functional/test-framework/test_tools/fs_utils.py b/test/functional/test-framework/test_tools/fs_utils.py
deleted file mode 100644
index 512bacc..0000000
--- a/test/functional/test-framework/test_tools/fs_utils.py
+++ /dev/null
@@ -1,378 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-import base64
-import math
-import textwrap
-
-from aenum import IntFlag, Enum
-from collections import namedtuple
-from datetime import datetime
-
-from core.test_run import TestRun
-from test_tools.dd import Dd
-from test_utils.size import Size, Unit
-
-
-class Permissions(IntFlag):
- r = 4
- w = 2
- x = 1
-
- def __str__(self):
- ret_string = ""
- for p in Permissions:
- if p in self:
- ret_string += p.name
- return ret_string
-
-
-class PermissionsUsers(IntFlag):
- u = 4
- g = 2
- o = 1
-
- def __str__(self):
- ret_string = ""
- for p in PermissionsUsers:
- if p in self:
- ret_string += p.name
- return ret_string
-
-
-class PermissionSign(Enum):
- add = '+'
- remove = '-'
- set = '='
-
-
-class FilesPermissions():
- perms_exceptions = {}
-
- def __init__(self, files_list: list):
- self.files_list = files_list
-
- def add_exceptions(self, perms: dict):
- self.perms_exceptions.update(perms)
-
- def check(self, file_perm: int = 644, dir_perm: int = 755):
- failed_perms = []
- FailedPerm = namedtuple("FailedPerm", ["file", "current_perm", "expected_perm"])
-
- for file in self.files_list:
- perm = get_permissions(file)
-
- if file in self.perms_exceptions:
- if perm != self.perms_exceptions[file]:
- failed_perms.append(FailedPerm(file, perm, self.perms_exceptions[file]))
- continue
-
- if check_if_regular_file_exists(file):
- if perm != file_perm:
- failed_perms.append(FailedPerm(file, perm, file_perm))
- elif check_if_directory_exists(file):
- if perm != dir_perm:
- failed_perms.append(FailedPerm(file, perm, dir_perm))
- else:
- raise Exception(f"{file}: File type not recognized.")
-
- return failed_perms
-
-
-def create_directory(path, parents: bool = False):
- cmd = f"mkdir {'--parents ' if parents else ''}\"{path}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def check_if_directory_exists(path):
- return TestRun.executor.run(f"test -d \"{path}\"").exit_code == 0
-
-
-def check_if_file_exists(path):
- return TestRun.executor.run(f"test -e \"{path}\"").exit_code == 0
-
-
-def check_if_regular_file_exists(path):
- return TestRun.executor.run(f"test -f \"{path}\"").exit_code == 0
-
-
-def check_if_symlink_exists(path):
- return TestRun.executor.run(f"test -L \"{path}\"").exit_code == 0
-
-
-def copy(source: str,
- destination: str,
- force: bool = False,
- recursive: bool = False,
- dereference: bool = False):
- cmd = f"cp{' --force' if force else ''}" \
- f"{' --recursive' if recursive else ''}" \
- f"{' --dereference' if dereference else ''} " \
- f"\"{source}\" \"{destination}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def move(source, destination, force: bool = False):
- cmd = f"mv{' --force' if force else ''} \"{source}\" \"{destination}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def remove(path, force: bool = False, recursive: bool = False, ignore_errors: bool = False):
- cmd = f"rm{' --force' if force else ''}{' --recursive' if recursive else ''} \"{path}\""
- output = TestRun.executor.run(cmd)
- if output.exit_code != 0 and not ignore_errors:
- raise Exception(f"Could not remove file {path}."
- f"\nstdout: {output.stdout}\nstderr: {output.stderr}")
- return output
-
-
-def get_permissions(path, dereference: bool = True):
- cmd = f"stat --format='%a' {'--dereference' if dereference else ''} \"{path}\""
- return int(TestRun.executor.run_expect_success(cmd).stdout)
-
-
-def chmod(path, permissions: Permissions, users: PermissionsUsers,
- sign: PermissionSign = PermissionSign.set, recursive: bool = False):
- cmd = f"chmod{' --recursive' if recursive else ''} " \
- f"{str(users)}{sign.value}{str(permissions)} \"{path}\""
- output = TestRun.executor.run(cmd)
- return output
-
-
-def chmod_numerical(path, permissions: int, recursive: bool = False):
- cmd = f"chmod{' --recursive' if recursive else ''} {permissions} \"{path}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def chown(path, owner, group, recursive):
- cmd = f"chown {'--recursive ' if recursive else ''}{owner}:{group} \"{path}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def create_file(path):
- if not path.strip():
- raise ValueError("Path cannot be empty or whitespaces.")
- cmd = f"touch \"{path}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def compare(file, other_file):
- output = TestRun.executor.run(
- f"cmp --silent \"{file}\" \"{other_file}\"")
- if output.exit_code == 0:
- return True
- elif output.exit_code > 1:
- raise Exception(f"Compare command execution failed. {output.stdout}\n{output.stderr}")
- else:
- return False
-
-
-def diff(file, other_file):
- output = TestRun.executor.run(
- f"diff \"{file}\" \"{other_file}\"")
- if output.exit_code == 0:
- return None
- elif output.exit_code > 1:
- raise Exception(f"Diff command execution failed. {output.stdout}\n{output.stderr}")
- else:
- return output.stderr
-
-
-# For some reason separators other than '/' don't work when using sed on system paths
-# This requires escaping '/' in pattern and target string
-def escape_sed_string(string: str, sed_replace: bool = False):
- string = string.replace("'", r"\x27").replace("/", r"\/")
- # '&' has special meaning in sed replace and needs to be escaped
- if sed_replace:
- string = string.replace("&", r"\&")
- return string
-
-
-def insert_line_before_pattern(file, pattern, new_line):
- pattern = escape_sed_string(pattern)
- new_line = escape_sed_string(new_line)
- cmd = f"sed -i '/{pattern}/i {new_line}' \"{file}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def replace_first_pattern_occurrence(file, pattern, new_string):
- pattern = escape_sed_string(pattern)
- new_string = escape_sed_string(new_string, sed_replace=True)
- cmd = f"sed -i '0,/{pattern}/s//{new_string}/' \"{file}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def replace_in_lines(file, pattern, new_string, regexp=False):
- pattern = escape_sed_string(pattern)
- new_string = escape_sed_string(new_string, sed_replace=True)
- cmd = f"sed -i{' -r' if regexp else ''} 's/{pattern}/{new_string}/g' \"{file}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def append_line(file, string):
- cmd = f"echo '{string}' >> \"{file}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def remove_lines(file, pattern, regexp=False):
- pattern = escape_sed_string(pattern)
- cmd = f"sed -i{' -r' if regexp else ''} '/{pattern}/d' \"{file}\""
- return TestRun.executor.run_expect_success(cmd)
-
-
-def read_file(file):
- if not file.strip():
- raise ValueError("File path cannot be empty or whitespace.")
- output = TestRun.executor.run_expect_success(f"cat \"{file}\"")
- return output.stdout
-
-
-def write_file(file, content, overwrite: bool = True, unix_line_end: bool = True):
- if not file.strip():
- raise ValueError("File path cannot be empty or whitespace.")
- if not content:
- raise ValueError("Content cannot be empty.")
- if unix_line_end:
- content.replace('\r', '')
- content += '\n'
- max_length = 60000
- split_content = textwrap.TextWrapper(width=max_length, replace_whitespace=False).wrap(content)
- split_content[-1] += '\n'
- for s in split_content:
- redirection_char = '>' if overwrite else '>>'
- overwrite = False
- encoded_content = base64.b64encode(s.encode("utf-8"))
- cmd = f"printf '{encoded_content.decode('utf-8')}' " \
- f"| base64 --decode {redirection_char} \"{file}\""
- TestRun.executor.run_expect_success(cmd)
-
-
-def uncompress_archive(file, destination=None):
- from test_utils.filesystem.file import File
-
- if not isinstance(file, File):
- file = File(file)
- if not destination:
- destination = file.parent_dir
- command = (f"unzip -u {file.full_path} -d {destination}"
- if str(file).endswith(".zip")
- else f"tar --extract --file={file.full_path} --directory={destination}")
- TestRun.executor.run_expect_success(command)
-
-
-def ls(path, options=''):
- default_options = "-lA --time-style=+'%Y-%m-%d %H:%M:%S'"
- output = TestRun.executor.run(
- f"ls {default_options} {options} \"{path}\"")
- return output.stdout
-
-
-def ls_item(path):
- output = ls(path, '-d')
- return output.splitlines()[0] if output else None
-
-
-def parse_ls_output(ls_output, dir_path=''):
- split_output = ls_output.split('\n')
- fs_items = []
- for line in split_output:
- if not line.strip():
- continue
- line_fields = line.split()
- if len(line_fields) < 8:
- continue
- file_type = line[0]
- if file_type not in ['-', 'd', 'l', 'b', 'c', 'p', 's']:
- continue
- permissions = line_fields[0][1:].replace('.', '')
- owner = line_fields[2]
- group = line_fields[3]
- has_size = ',' not in line_fields[4]
- if has_size:
- size = Size(float(line_fields[4]), Unit.Byte)
- else:
- size = None
- line_fields.pop(4)
- split_date = line_fields[5].split('-')
- split_time = line_fields[6].split(':')
- modification_time = datetime(int(split_date[0]), int(split_date[1]), int(split_date[2]),
- int(split_time[0]), int(split_time[1]), int(split_time[2]))
- if dir_path and file_type != 'l':
- full_path = '/'.join([dir_path, line_fields[7]])
- else:
- full_path = line_fields[7]
-
- from test_utils.filesystem.file import File, FsItem
- from test_utils.filesystem.directory import Directory
- from test_utils.filesystem.symlink import Symlink
-
- if file_type == '-':
- fs_item = File(full_path)
- elif file_type == 'd':
- fs_item = Directory(full_path)
- elif file_type == 'l':
- fs_item = Symlink(full_path)
- else:
- fs_item = FsItem(full_path)
-
- fs_item.permissions.user = Permissions['|'.join(list(permissions[:3].replace('-', '')))] \
- if permissions[:3] != '---' else Permissions(0)
- fs_item.permissions.group = Permissions['|'.join(list(permissions[3:6].replace('-', '')))] \
- if permissions[3:6] != '---' else Permissions(0)
- fs_item.permissions.other = Permissions['|'.join(list(permissions[6:].replace('-', '')))] \
- if permissions[6:] != '---' else Permissions(0)
-
- fs_item.owner = owner
- fs_item.group = group
- fs_item.size = size
- fs_item.modification_time = modification_time
- fs_items.append(fs_item)
- return fs_items
-
-
-def find_all_files(path: str, recursive: bool = True):
- if not path.strip():
- raise ValueError("No path given.")
-
- output = TestRun.executor.run_expect_success(f"find \"{path}\" {'-maxdepth 1' if not recursive else ''} \( -type f -o -type l \) -print")
-
- return output.stdout.splitlines()
-
-
-def find_all_dirs(path: str, recursive: bool = True):
- if not path.strip():
- raise ValueError("No path given.")
-
- output = TestRun.executor.run_expect_success(f"find \"{path}\" {'-maxdepth 1' if not recursive else ''} -type d -print")
-
- return output.stdout.splitlines()
-
-
-def find_all_items(path: str, recursive: bool = True):
- return [*find_all_files(path, recursive), *find_all_dirs(path, recursive)]
-
-
-def readlink(link: str, options="--canonicalize-existing"):
- return TestRun.executor.run_expect_success(
- f"readlink {options} \"{link}\""
- ).stdout
-
-
-def create_random_test_file(target_file_path: str,
- file_size: Size = Size(1, Unit.MebiByte),
- random: bool = True):
- from test_utils.filesystem.file import File
- bs = Size(512, Unit.KibiByte)
- cnt = math.ceil(file_size.value / bs.value)
- file = File.create_file(target_file_path)
- dd = Dd().output(target_file_path) \
- .input("/dev/urandom" if random else "/dev/zero") \
- .block_size(bs) \
- .count(cnt) \
- .oflag("direct")
- dd.run()
- file.refresh_item()
- return file
diff --git a/test/functional/test-framework/test_tools/iostat.py b/test/functional/test-framework/test_tools/iostat.py
deleted file mode 100644
index 3e310bf..0000000
--- a/test/functional/test-framework/test_tools/iostat.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#
-# Copyright(c) 2020-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_utils.size import Size, Unit, UnitPerSecond
-from test_utils.time import Time
-import csv
-
-
-class IOstatExtended:
- iostat_option = "x"
-
- def __init__(self, device_statistics: dict):
-
- # Notes about params:
- # await param is displayed only on flag -s
- # avgrq-sz doesn't appear in newer versions of iostat -x
-
- self.device_name = device_statistics["Device"]
- # rrqm/s
- self.read_requests_merged_per_sec = float(device_statistics["rrqm/s"])
- # wrqm/s
- self.write_requests_merged_per_sec = float(device_statistics["wrqm/s"])
- # r/s
- self.read_requests_per_sec = float(device_statistics["r/s"])
- # w/s
- self.write_requests_per_sec = float(device_statistics["w/s"])
- # rkB/s
- self.reads_per_sec = Size(float(device_statistics["rkB/s"]), UnitPerSecond(Unit.KiloByte))
- # wkB/s
- self.writes_per_sec = Size(float(device_statistics["wkB/s"]), UnitPerSecond(Unit.KiloByte))
- # avgqu-sz - in newer versions is named aqu-sz
- self.average_queue_length = float(
- device_statistics["aqu-sz"]
- if "aqu-sz" in device_statistics
- else device_statistics.get("avgqu-sz", 0)
- )
- # r_await
- self.read_average_service_time = Time(milliseconds=float(device_statistics["r_await"]))
- # w_await
- self.write_average_service_time = Time(milliseconds=float(device_statistics["w_await"]))
- # iostat's documentation says to not trust 11th field
- # util
- self.utilization = float(device_statistics["%util"])
-
- def __str__(self):
- return (
- f"\n=========={self.device_name} IO stats: ==========\n"
- f"Read requests merged per second: {self.read_requests_merged_per_sec}\n"
- f"Write requests merged per second: {self.write_requests_merged_per_sec}\n"
- f"Read requests: {self.read_requests_per_sec}\n"
- f"Write requests: {self.write_requests_per_sec}\n"
- f"Reads per second: {self.reads_per_sec}\n"
- f"Writes per second {self.writes_per_sec}\n"
- f"Average queue length {self.average_queue_length}\n"
- f"Read average service time {self.read_average_service_time}\n"
- f"Write average service time: {self.write_average_service_time}\n"
- f"Utilization: {self.utilization}\n"
- f"=================================================\n"
- )
-
- def __repr__(self):
- return str(self)
-
- def __eq__(self, other):
- if not other:
- return False
- return (
- self.read_requests_merged_per_sec == other.read_requests_merged_per_sec
- and self.write_requests_merged_per_sec == other.write_requests_merged_per_sec
- and self.read_requests_per_sec == other.read_requests_per_sec
- and self.write_requests_per_sec == other.write_requests_per_sec
- and self.reads_per_sec == other.reads_per_sec
- and self.writes_per_sec == other.writes_per_sec
- and self.average_queue_length == other.average_queue_length
- and self.read_average_service_time == other.read_average_service_time
- and self.write_average_service_time == other.write_average_service_time
- and self.utilization == other.utilization
- )
-
- @classmethod
- def get_iostat_list(
- cls,
- devices_list: [Device],
- since_boot: bool = True,
- interval: int = 1,
- ):
- """
- Returns list of IOstat objects containing extended statistics displayed
- in kibibytes/kibibytes per second.
- """
- return _get_iostat_list(cls, devices_list, since_boot, interval)
-
-
-class IOstatBasic:
- iostat_option = "d"
-
- def __init__(self, device_statistics):
-
- self.device_name = device_statistics["Device"]
- # tps
- self.transfers_per_second = float(device_statistics["tps"])
- # kB_read/s
- self.reads_per_second = Size(
- float(device_statistics["kB_read/s"]), UnitPerSecond(Unit.KiloByte)
- )
- # kB_wrtn/s
- self.writes_per_second = Size(
- float(device_statistics["kB_wrtn/s"]), UnitPerSecond(Unit.KiloByte)
- )
- # kB_read
- self.total_reads = Size(float(device_statistics["kB_read"]), Unit.KibiByte)
- # kB_wrtn
- self.total_writes = Size(float(device_statistics["kB_wrtn"]), Unit.KibiByte)
-
- def __str__(self):
- return (
- f"\n=========={self.device_name} IO stats: ==========\n"
- f"Transfers per second: {self.transfers_per_second}\n"
- f"Kilobytes read per second: {self.reads_per_second}\n"
- f"Kilobytes written per second: {self.writes_per_second}\n"
- f"Kilobytes read: {self.total_reads}\n"
- f"Kilobytes written: {self.total_writes}\n"
- f"=================================================\n"
- )
-
- def __repr__(self):
- return str(self)
-
- def __eq__(self, other):
- if not isinstance(other, IOstatBasic):
- return False
- return vars(self) == vars(other)
-
- @classmethod
- def get_iostat_list(
- cls,
- devices_list: [Device],
- since_boot: bool = True,
- interval: int = 1,
- ):
- """
- Returns list of IOstat objects containing basic statistics displayed
- in kibibytes/kibibytes per second.
- """
- return _get_iostat_list(cls, devices_list, since_boot, interval)
-
-
-def _get_iostat_list(
- class_type: type,
- devices_list: [Device],
- since_boot: bool,
- interval: int,
-):
- if interval < 1:
- raise ValueError("iostat interval must be positive!")
-
- iostat_cmd = f"iostat -k -{class_type.iostat_option} "
-
- if not since_boot:
- iostat_cmd += f"-y {interval} 1 "
-
- iostat_cmd += " ".join([name.get_device_id() for name in devices_list])
-
- sed_cmd = "sed -n '/^$/d;s/\s\+/,/g;/^Device/,$p'"
-
- cmd = f"{iostat_cmd} | {sed_cmd}"
-
- lines = TestRun.executor.run(cmd).stdout.splitlines()
- table_contents = csv.DictReader(lines, delimiter=",")
-
- ret = []
- for device in table_contents:
- ret += [class_type(device)]
-
- return ret
diff --git a/test/functional/test-framework/test_tools/kedr.py b/test/functional/test-framework/test_tools/kedr.py
deleted file mode 100644
index cceb43f..0000000
--- a/test/functional/test-framework/test_tools/kedr.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import wget
-import os
-from enum import Enum
-
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_utils.os_utils import DEBUGFS_MOUNT_POINT
-
-
-KEDR_0_6_URL = "https://github.com/euspectre/kedr/archive/v0.6.tar.gz"
-BUILD_DIR = "build"
-LEAKS_LOGS_PATH = f"{DEBUGFS_MOUNT_POINT}/kedr_leak_check"
-KMALLOC_FAULT_SIMULATION_PATH = "/sys/kernel/debug/kedr_fault_simulation"
-
-
-class KedrProfile(Enum):
- MEM_LEAK_CHECK = "leak_check.conf"
- FAULT_SIM = "fsim.conf"
-
-
-class Kedr:
- @staticmethod
- def is_installed():
- return "KEDR version" in TestRun.executor.run("kedr --version").stdout.strip()
-
- @classmethod
- def install(cls):
- if cls.is_installed():
- TestRun.LOGGER.info("Kedr is already installed!")
- return
-
- # TODO check if cmake is installed before
- # TODO consider using os_utils.download_file()
- kedr_archive = wget.download(KEDR_0_6_URL)
-
- TestRun.executor.rsync_to(
- f"\"{kedr_archive}\"",
- f"{TestRun.config['working_dir']}")
-
- kedr_dir = TestRun.executor.run_expect_success(
- f"cd {TestRun.config['working_dir']} && "
- f"tar -ztf \"{kedr_archive}\" | sed -e 's@/.*@@' | uniq"
- ).stdout
-
- TestRun.executor.run_expect_success(
- f"cd {TestRun.config['working_dir']} && "
- f"tar -xf \"{kedr_archive}\" && "
- f"cd {kedr_dir} && "
- f"mkdir -p {BUILD_DIR} && "
- f"cd {BUILD_DIR} && "
- f"cmake ../sources/ && "
- f"make && "
- f"make install"
- )
-
- os.remove(kedr_archive)
- TestRun.LOGGER.info("Kedr installed succesfully")
-
- @classmethod
- def is_loaded(cls):
- if not cls.is_installed():
- raise Exception("Kedr is not installed!")
-
- if "KEDR status: loaded" in TestRun.executor.run_expect_success("kedr status").stdout:
- return True
- else:
- return False
-
- @classmethod
- def start(cls, module, profile: KedrProfile = KedrProfile.MEM_LEAK_CHECK):
- if not cls.is_installed():
- raise Exception("Kedr is not installed!")
-
- TestRun.LOGGER.info(f"Starting kedr with {profile} profile")
- start_cmd = f"kedr start {module} -f {profile.value}"
- TestRun.executor.run_expect_success(start_cmd)
-
- # TODO extend to scenarios other than kmalloc
- def setup_fault_injections(condition: str = "1"):
- TestRun.executor.run_expect_success(
- f'echo "kmalloc" > {KMALLOC_FAULT_SIMULATION_PATH}/points/kmalloc/current_indicator')
- TestRun.executor.run_expect_success(
- f'echo "{condition}" > {KMALLOC_FAULT_SIMULATION_PATH}/points/kmalloc/expression')
-
- @classmethod
- def fsim_show_last_fault(cls):
- if not cls.is_installed():
- raise Exception("Kedr is not installed!")
-
- if not cls.is_loaded():
- raise Exception("Kedr is not loaded!")
-
- return fs_utils.read_file(f"{KMALLOC_FAULT_SIMULATION_PATH}/last_fault")
-
- @classmethod
- def stop(cls):
- if not cls.is_installed():
- raise Exception("Kedr is not installed!")
-
- TestRun.executor.run_expect_success("kedr stop")
-
- @classmethod
- def check_for_mem_leaks(cls, module):
- if not cls.is_installed():
- raise Exception("Kedr is not installed!")
-
- if not cls.is_loaded():
- raise Exception("Kedr is not loaded!")
-
- if fs_utils.check_if_directory_exists(f"{LEAKS_LOGS_PATH}/{module}"):
- logs_path = f"{LEAKS_LOGS_PATH}/{module}"
- elif fs_utils.check_if_directory_exists(f"{DEBUGFS_MOUNT_POINT}"):
- logs_path = f"{LEAKS_LOGS_PATH}"
- else:
- raise Exception("Couldn't find kedr logs dir!")
-
- leaks = fs_utils.read_file(f"{logs_path}/possible_leaks")
- frees = fs_utils.read_file(f"{logs_path}/unallocated_frees")
- summary = fs_utils.read_file(f"{logs_path}/info")
- if leaks or frees:
- raise Exception("Memory leaks found!\n"
- f"Kedr summary: {summary}\n"
- f"Possible memory leaks: {leaks}\n"
- f"Unallocated frees: {frees}\n")
diff --git a/test/functional/test-framework/test_tools/mdadm.py b/test/functional/test-framework/test_tools/mdadm.py
deleted file mode 100644
index ae962bb..0000000
--- a/test/functional/test-framework/test_tools/mdadm.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import re
-
-from core.test_run import TestRun
-from test_utils.size import Unit
-
-
-class Mdadm:
- @staticmethod
- def assemble(device_paths: str = None):
- cmd = f"mdadm --assemble " + (device_paths if device_paths else "--scan")
- return TestRun.executor.run(cmd)
-
- @staticmethod
- def create(conf, device_paths: str):
- if not conf.name:
- raise ValueError("Name needed for RAID creation.")
- if not device_paths:
- raise ValueError("Device paths needed for RAID creation.")
-
- cmd = f"mdadm --create --run /dev/md/{conf.name} "
- if conf.metadata.value != "legacy":
- cmd += f"--metadata={conf.metadata.value} "
- if conf.level is not None:
- cmd += f"--level={conf.level.value} "
- if conf.number_of_devices:
- cmd += f"--raid-devices={conf.number_of_devices} "
- if conf.strip_size:
- cmd += f"--chunk={conf.strip_size} "
- if conf.size:
- cmd += f"--size={int(conf.size.get_value(Unit.KibiByte))} "
- cmd += device_paths
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def detail(raid_device_paths: str):
- if not raid_device_paths:
- raise ValueError("Provide paths of RAID devices to show details for.")
- cmd = f"mdadm --detail {raid_device_paths} --prefer=by-id"
- return TestRun.executor.run_expect_success(cmd)
-
- @classmethod
- def detail_result(cls, raid_device_paths: str):
- output = cls.detail(raid_device_paths)
- details = {}
- for device_details in re.split("^/dev/", output.stdout, flags=re.MULTILINE):
- if not device_details:
- continue
- lines = device_details.splitlines()
- key = "/dev/" + lines[0].rstrip(':')
- details[key] = {}
- details[key]["path"] = key
- details[key]["devices"] = cls.__parse_devices(device_details)
- details[key]["level"] = cls.__parse_level(device_details)
- details[key]["uuid"] = cls.__parse_uuid(device_details)
- metadata = cls.__parse_metadata(device_details)
- if metadata:
- details[key]["metadata"] = metadata
-
- return details
-
- @staticmethod
- def examine(brief: bool = True, device_paths: str = None):
- cmd = f"mdadm --examine "
- if brief:
- cmd += "--brief "
- cmd += (device_paths if device_paths else "--scan")
- return TestRun.executor.run_expect_success(cmd)
-
- @classmethod
- def examine_result(cls, device_paths: str = None):
- output = cls.examine(device_paths=device_paths)
- raids = []
-
- uuid_path_prefix = "/dev/disk/by-id/md-uuid-"
- # sometimes links for RAIDs are not properly created, force udev to create them
- TestRun.executor.run("udevadm trigger && udevadm settle")
-
- for line in output.stdout.splitlines():
- split_line = line.split()
- try:
- uuid = [i for i in split_line if i.startswith("UUID=")][0].split("=")[-1]
- except IndexError:
- continue
- raid_link = uuid_path_prefix + uuid
- raid = Mdadm.detail_result(raid_link)[raid_link]
- if raid["level"] == "Container":
- continue
- raid["metadata"], raid["array_devices"] = "legacy", []
- container = (
- [i for i in split_line if i.startswith("container=")][0]
- if "container=" in line else None
- )
- if container:
- container_link = uuid_path_prefix + container.split("=")[-1]
- raid["container"] = cls.detail_result(container_link)[container_link]
- raid["metadata"] = raid["container"]["metadata"]
- raid["array_devices"] = raid["container"]["devices"]
- raids.append(raid)
- return raids
-
- @staticmethod
- def stop(device_paths: str = None):
- cmd = f"mdadm --stop " + (device_paths if device_paths else "--scan")
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def zero_superblock(device_paths: str):
- cmd = f"mdadm --zero-superblock {device_paths}"
- return TestRun.executor.run_expect_success(cmd)
-
- @staticmethod
- def __parse_devices(details: str):
- devices = []
- for detail in [d.strip() for d in details.splitlines() if " /dev/" in d]:
- devices.append(detail.split()[-1])
- return devices
-
- @staticmethod
- def __parse_level(details: str):
- level = [line for line in details.splitlines() if "Raid Level" in line][0].split(" : ")[-1]
- return level.capitalize()
-
- @staticmethod
- def __parse_uuid(details: str):
- uuid = [line for line in details.splitlines() if "UUID" in line][0].split(" : ")[-1]
- return uuid
-
- @staticmethod
- def __parse_metadata(details: str):
- try:
- return [
- line.strip() for line in details.splitlines()
- if line.strip().startswith("Version :")
- ][0].split(" : ")[-1]
- except IndexError:
- return None
diff --git a/test/functional/test-framework/test_tools/nvme_cli.py b/test/functional/test-framework/test_tools/nvme_cli.py
deleted file mode 100644
index 5844587..0000000
--- a/test/functional/test-framework/test_tools/nvme_cli.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Copyright(c) 2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import json
-from core.test_run import TestRun
-
-
-def format_disk(device, metadata_size=None, block_size=None,
- force=True, format_params=None, reset=True):
- force_param = '-f' if force else ''
- reset_param = '-r' if reset else ''
- format_params = ' '.join(format_params) if format_params else ''
- lbafs = get_lba_formats(device)
- if metadata_size:
- lbafs = [lbaf for lbaf in lbafs if lbaf['metadata_size'] == metadata_size]
- if block_size:
- lbafs = [lbaf for lbaf in lbafs if lbaf['block_size'] == block_size]
- if len(lbafs) == 1:
- TestRun.LOGGER.info(
- f"Formatting device {device.path} with {metadata_size} metadata size "
- f"and {lbafs[0]['block_size']} block size")
- TestRun.executor.run_expect_success(
- f"nvme format {device.path} -l {lbafs[0]['lba_format']} "
- f"{force_param} {reset_param} {format_params}")
- TestRun.LOGGER.info(f"Successfully format device: {device.path}")
- else:
- raise Exception(f"Wrong parameters to format device: {device.path}")
- elif block_size:
- lbafs = [lbaf for lbaf in lbafs if lbaf['block_size'] == block_size]
- if len(lbafs) > 0:
- TestRun.LOGGER.info(
- f"Formatting device {device.path} with {block_size} block size")
- TestRun.executor.run_expect_success(
- f"nvme format {device.path} -b {block_size} "
- f"{force_param} {reset_param} {format_params}")
- TestRun.LOGGER.info(f"Successfully format device: {device.path}")
- else:
- raise Exception(f"Wrong parameters to format device: {device.path}")
- else:
- raise Exception("Cannot format device without specified parameters")
-
-
-def get_lba_formats(device):
- output = json.loads(TestRun.executor.run_expect_success(
- f"nvme id-ns {device.path} -o json").stdout)
- entries = output['lbafs']
- lbafs = []
- for entry in entries:
- lbaf = {"lba_format": entries.index(entry),
- "metadata_size": entry['ms'],
- "block_size": 2 ** entry['ds'],
- "in_use": entries.index(entry) == output['flbas']}
- lbafs.append(lbaf)
- return lbafs
-
-
-def get_lba_format_in_use(device):
- lbafs = get_lba_formats(device)
- return next((lbaf for lbaf in lbafs if lbaf['in_use']))
diff --git a/test/functional/test-framework/test_tools/packaging.py b/test/functional/test-framework/test_tools/packaging.py
deleted file mode 100644
index 01935d8..0000000
--- a/test/functional/test-framework/test_tools/packaging.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-import os
-import re
-
-from core.test_run import TestRun
-from test_utils.output import CmdException
-
-
-class RpmSet():
- def __init__(self, packages_paths: list):
- self.packages = packages_paths
-
- def _get_package_names(self):
- return " ".join([os.path.splitext(os.path.basename(pckg))[0] for pckg in self.packages])
-
- def check_if_installed(self):
- if not self.packages:
- raise ValueError("No packages given.")
-
- output = TestRun.executor.run(f"rpm --query {self._get_package_names()}")
-
- return output.exit_code == 0
-
- def install(self):
- TestRun.LOGGER.info(f"Installing RPM packages")
-
- if not self.packages:
- raise ValueError("No packages given.")
-
- output = TestRun.executor.run(
- f"rpm --upgrade --verbose --replacepkgs {' '.join(self.packages)}"
- )
- if (
- output.exit_code != 0
- or re.search("error", output.stdout, re.IGNORECASE)
- or re.search("error", output.stderr, re.IGNORECASE)
- ):
- raise CmdException("Installation failed or errors found during the process.", output)
-
- def uninstall(self):
- TestRun.LOGGER.info(f"Uninstalling RPM packages")
-
- if not self.check_if_installed():
- raise FileNotFoundError("Could not uninstall - packages not installed yet.")
-
- output = TestRun.executor.run(f"rpm --erase --verbose {self._get_package_names()}")
- if (
- output.exit_code != 0
- or re.search("error", output.stdout, re.IGNORECASE)
- or re.search("error", output.stderr, re.IGNORECASE)
- ):
- raise CmdException("Uninstallation failed or errors found during the process.", output)
-
- @staticmethod
- def uninstall_all_matching(*packages_names: str):
- for name in packages_names:
- TestRun.LOGGER.info(f"Uninstalling all RPM packages matching '{name}'")
- TestRun.executor.run_expect_success(
- f"rpm --query --all | grep {name} | "
- f"xargs --no-run-if-empty rpm --erase --verbose"
- )
-
-
-class DebSet():
- def __init__(self, packages_paths: list):
- self.packages = packages_paths
-
- def _get_package_names(self):
- return " ".join([os.path.basename(pckg).split("_")[0] for pckg in self.packages])
-
- def check_if_installed(self):
- if not self.packages:
- raise ValueError("No packages given.")
-
- output = TestRun.executor.run(f"dpkg --no-pager --list {self._get_package_names()}")
-
- return output.exit_code == 0
-
- def install(self):
- TestRun.LOGGER.info(f"Installing DEB packages")
-
- if not self.packages:
- raise ValueError("No packages given.")
-
- output = TestRun.executor.run(
- f"dpkg --force-confdef --force-confold --install {' '.join(self.packages)}"
- )
- if (
- output.exit_code != 0
- or re.search("error", output.stdout, re.IGNORECASE)
- or re.search("error", output.stderr, re.IGNORECASE)
- ):
- raise CmdException("Installation failed or errors found during the process.", output)
-
- def uninstall(self):
- TestRun.LOGGER.info(f"Uninstalling DEB packages")
-
- if not self.check_if_installed():
- raise FileNotFoundError("Could not uninstall - packages not installed yet.")
-
- output = TestRun.executor.run(f"dpkg --purge {self._get_package_names()}")
- if (
- output.exit_code != 0
- or re.search("error", output.stdout, re.IGNORECASE)
- or re.search("error", output.stderr, re.IGNORECASE)
- ):
- raise CmdException("Uninstallation failed or errors found during the process.", output)
-
- @staticmethod
- def uninstall_all_matching(*packages_names: str):
- for name in packages_names:
- TestRun.LOGGER.info(f"Uninstalling all DEB packages matching '{name}'")
- TestRun.executor.run_expect_success(
- f"dpkg-query --no-pager --showformat='${{Package}}\n' --show | grep {name} | "
- f"xargs --no-run-if-empty dpkg --purge"
- )
diff --git a/test/functional/test-framework/test_tools/peach_fuzzer/__init__.py b/test/functional/test-framework/test_tools/peach_fuzzer/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/test_tools/peach_fuzzer/config_template.xml b/test/functional/test-framework/test_tools/peach_fuzzer/config_template.xml
deleted file mode 100644
index 1c6c8a8..0000000
--- a/test/functional/test-framework/test_tools/peach_fuzzer/config_template.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/functional/test-framework/test_tools/peach_fuzzer/peach_fuzzer.py b/test/functional/test-framework/test_tools/peach_fuzzer/peach_fuzzer.py
deleted file mode 100644
index 4adb3a3..0000000
--- a/test/functional/test-framework/test_tools/peach_fuzzer/peach_fuzzer.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-# Copyright(c) 2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import os
-import wget
-import base64
-import posixpath
-import random
-import tempfile
-import lxml.etree as etree
-from collections import namedtuple
-
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_tools.fs_utils import create_directory, check_if_file_exists, write_file
-
-
-class PeachFuzzer:
- """
- API to work with Peach Fuzzer tool in Test-Framework.
- Peach Fuzzer is used only for generating fuzzed values that later are used in Test-Framework
- in order to execute fuzzed CLI commands or to prepare fuzzed config files.
- """
-
- peach_fuzzer_3_0_url = "https://sourceforge.net/projects/peachfuzz/files/Peach/3.0/" \
- "peach-3.0.202-linux-x86_64-release.zip"
- base_dir = "/root/Fuzzy"
- peach_dir = "peach-3.0.202-linux-x86_64-release"
- xml_config_template = posixpath.join(posixpath.dirname(__file__), "config_template.xml")
- xml_config_file = posixpath.join(base_dir, "fuzzerConfig.xml")
- xml_namespace = "http://peachfuzzer.com/2012/Peach"
- fuzzy_output_file = posixpath.join(base_dir, "fuzzedParams.txt")
- tested_param_placeholder = b"{param}"
- # escape backslash first, so it doesn't interfere with escaping other characters
- escape_chars = '\\\n"\'&|;()`<>$! '
-
- @classmethod
- def get_fuzzed_command(cls, command_template: bytes, count: int):
- """
- Generate command with fuzzed parameter provided on command_template.
- Command is ready to be executed with test executor
- :param command_template: byte string with command to be executed.
- parameter to be replaced with fuzzed string has to be tested_param_placeholder
- :param count: amount of fuzzed commands to generate
- :returns: named tuple with fuzzed param and CLI ready to be executed with Test-Framework
- executors. Param is returned in order to implement correct values checkers in the tests
- """
- TestRun.LOGGER.info(f"Try to get commands with fuzzed parameters")
- FuzzedCommand = namedtuple('FuzzedCommand', ['param', 'command'])
- if cls.tested_param_placeholder not in command_template:
- TestRun.block("No param placeholder is found in command template!")
- cmd_prefix = b"echo "
- cmd_suffix = b" | base64 --decode | sh"
- for fuzzed_parameter in cls.generate_peach_fuzzer_parameters(count):
- yield FuzzedCommand(fuzzed_parameter,
- cmd_prefix + base64.b64encode(command_template.replace(
- cls.tested_param_placeholder, fuzzed_parameter)) + cmd_suffix)
-
- @classmethod
- def generate_peach_fuzzer_parameters(cls, count: int):
- """
- Generate fuzzed parameter according to Peach Fuzzer XML config
- Fuzzed parameter later can be used for either generating cli command or config.
- :param count: amount of fuzzed strings to generate
- :returns: fuzzed value in byte string
- """
- if not cls._is_installed():
- TestRun.LOGGER.info("Try to install Peach Fuzzer")
- cls._install()
- if not cls._is_xml_config_prepared():
- TestRun.block("No Peach Fuzzer XML config needed to generate fuzzed values was found!")
- fs_utils.remove(cls.fuzzy_output_file, force=True, ignore_errors=True)
- TestRun.LOGGER.info(f"Generate {count} unique fuzzed values")
- cmd = f"cd {cls.base_dir}; {cls.peach_dir}/peach --range 0,{count - 1} " \
- f"--seed {random.randrange(2 ** 32)} {cls.xml_config_file} > " \
- f"{cls.base_dir}/peachOutput.log"
- TestRun.executor.run_expect_success(cmd)
- if not check_if_file_exists(cls.fuzzy_output_file):
- TestRun.block("No expected fuzzy output file was found!")
-
- # process fuzzy output file locally on the controller as it can be very big
- local_fuzzy_file = tempfile.NamedTemporaryFile(delete=False)
- local_fuzzy_file.close()
- TestRun.executor.rsync_from(cls.fuzzy_output_file, local_fuzzy_file.name)
- with open(local_fuzzy_file.name, "r") as fd:
- for fuzzed_param_line in fd:
- fuzzed_param_bytes = base64.b64decode(fuzzed_param_line)
- fuzzed_param_bytes = cls._escape_special_chars(fuzzed_param_bytes)
- yield fuzzed_param_bytes
-
- @classmethod
- def generate_config(cls, data_model_config: list):
- """
- Generate Peach Fuzzer XML config based on template provided in xml_config_template
- and data template passed as an argument.
- :param data_model_config: dictionary with config that has to be used for generating
- DataModel section in PeachFuzzer XML config. Config can be stored in test in more compact
- form, e.g. in yaml, and can be converted to dict just before passing to this function.
- Example of such config in yaml:
- - name: String
- attributes:
- name: CacheId
- value: '1'
- size: '14'
- mutable: 'true'
- children:
- - name: Hint
- attributes:
- name: NumericalString
- value: 'true'
- """
-
- if not posixpath.exists(cls.xml_config_template):
- TestRun.block("Peach fuzzer xml config template not found!")
- root = etree.parse(cls.xml_config_template)
- data_model = root.find(f'{{{cls.xml_namespace}}}DataModel[@name="Value"]')
- cls.__create_xml_nodes(data_model, data_model_config)
- create_directory(cls.base_dir, True)
- write_file(cls.xml_config_file, etree.tostring(root, encoding="unicode"))
-
- @classmethod
- def copy_config(cls, config_file: str):
- """
- Instead of generating config with "generate_config" method, config can be prepared manually
- and just passed as is to PeachFuzzer.
- :param config_file: Peach Fuzzer XML config to be copied to the DUT
- """
- if not posixpath.exists(config_file):
- TestRun.block("Peach fuzzer xml config to be copied doesn't exist!")
- create_directory(cls.base_dir, True)
- TestRun.executor.rsync_to(config_file, cls.xml_config_file)
-
- @classmethod
- def __create_xml_nodes(cls, xml_node, config):
- """
- Create XML code for Peach Fuzzer based on python dict config
- """
- for element in config:
- new_node = etree.Element(element["name"])
- for attr_name, attr_value in element["attributes"].items():
- new_node.set(attr_name, attr_value)
- if element.get("children"):
- cls.__create_xml_nodes(new_node, element.get("children"))
- xml_node.append(new_node)
-
- @classmethod
- def _install(cls):
- """
- Install Peach Fuzzer on the DUT
- """
- peach_archive = wget.download(cls.peach_fuzzer_3_0_url)
- create_directory(cls.base_dir, True)
- TestRun.executor.rsync_to(f"\"{peach_archive}\"", f"{cls.base_dir}")
- TestRun.executor.run_expect_success(
- f'cd {cls.base_dir} && unzip -u "{peach_archive}"')
- if cls._is_installed():
- TestRun.LOGGER.info("Peach fuzzer installed successfully")
- os.remove(peach_archive)
- else:
- TestRun.block("Peach fuzzer installation failed!")
-
- @classmethod
- def _is_installed(cls):
- """
- Check if Peach Fuzzer is installed on the DUT
- """
- if not cls._is_mono_installed():
- TestRun.block("Mono is not installed, can't continue with Peach Fuzzer!")
- if fs_utils.check_if_directory_exists(posixpath.join(cls.base_dir, cls.peach_dir)):
- return "Peach" in TestRun.executor.run(
- f"cd {cls.base_dir} && {cls.peach_dir}/peach --version").stdout.strip()
- else:
- return False
-
- @classmethod
- def _escape_special_chars(cls, fuzzed_str: bytes):
- """
- Escape special chars provided in escape_chars list in the fuzzed string generated by
- Peach Fuzzer
- Escaping is done for example in order to make fuzzed string executable in Linux CLI
- If fuzzed string will be used in other places, escape_chars list may be overwritten.
- """
- for i in cls.escape_chars:
- i = bytes(i, "utf-8")
- if i in fuzzed_str[:]:
- fuzzed_str = fuzzed_str.replace(i, b'\\' + i)
- return fuzzed_str
-
- @classmethod
- def _is_xml_config_prepared(cls):
- """
- Check if Peach Fuzzer XML config is present on the DUT
- """
- if fs_utils.check_if_file_exists(cls.xml_config_file):
- return True
- else:
- return False
-
- @staticmethod
- def _is_mono_installed():
- """
- Check if Mono (.NET compatible framework) is installed on the DUT
- If it's not, it has to be installed manually.
- For RHEL-based OSes it's usually mono-complete package
- """
- return TestRun.executor.run("which mono").exit_code == 0
diff --git a/test/functional/test-framework/test_utils/__init__.py b/test/functional/test-framework/test_utils/__init__.py
deleted file mode 100644
index dce958c..0000000
--- a/test/functional/test-framework/test_utils/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/test/functional/test-framework/test_utils/asynchronous.py b/test/functional/test-framework/test_utils/asynchronous.py
deleted file mode 100644
index 9be0159..0000000
--- a/test/functional/test-framework/test_utils/asynchronous.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import concurrent
-
-
-def start_async_func(func, *args):
- """
- Starts asynchronous task and returns an Future object, which in turn returns an
- actual result after triggering result() method on it.
- - result() method is waiting for the task to be completed.
- - done() method returns True when task ended (have a result or ended with an exception)
- otherwise returns False
- """
- executor = concurrent.futures.ThreadPoolExecutor()
- return executor.submit(func, *args)
diff --git a/test/functional/test-framework/test_utils/disk_finder.py b/test/functional/test-framework/test_utils/disk_finder.py
deleted file mode 100644
index 21eb0db..0000000
--- a/test/functional/test-framework/test_utils/disk_finder.py
+++ /dev/null
@@ -1,190 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import posixpath
-
-from core.test_run import TestRun
-from test_tools import disk_utils
-from test_tools.fs_utils import check_if_file_exists, readlink
-from test_utils import os_utils
-from test_utils.output import CmdException
-
-
-def find_disks():
- devices_result = []
-
- TestRun.LOGGER.info("Finding platform's disks.")
-
- # TODO: intelmas should be implemented as a separate tool in the future.
- # There will be intelmas installer in case, when it is not installed
- output = TestRun.executor.run('intelmas')
- if output.exit_code != 0:
- raise Exception(f"Error while executing command: 'intelmas'.\n"
- f"stdout: {output.stdout}\nstderr: {output.stderr}")
- block_devices = get_block_devices_list()
- try:
- discover_ssd_devices(block_devices, devices_result)
- discover_hdd_devices(block_devices, devices_result)
- except Exception as e:
- raise Exception(f"Exception occurred while looking for disks: {str(e)}")
-
- return devices_result
-
-
-def get_block_devices_list():
- devices = TestRun.executor.run_expect_success("ls /sys/block -1").stdout.splitlines()
- os_disks = get_system_disks()
- block_devices = []
-
- for dev in devices:
- if ('sd' in dev or 'nvme' in dev) and dev not in os_disks:
- block_devices.append(dev)
-
- return block_devices
-
-
-def discover_hdd_devices(block_devices, devices_res):
- for dev in block_devices:
- if TestRun.executor.run_expect_success(f"cat /sys/block/{dev}/removable").stdout == "1":
- continue # skip removable drives
- block_size = disk_utils.get_block_size(dev)
- if int(block_size) == 4096:
- disk_type = 'hdd4k'
- else:
- disk_type = 'hdd'
- devices_res.append({
- "type": disk_type,
- "path": f"{resolve_to_by_id_link(dev)}",
- "serial": TestRun.executor.run_expect_success(
- f"sg_inq /dev/{dev} | grep -i 'serial number'"
- ).stdout.split(': ')[1].strip(),
- "blocksize": block_size,
- "size": disk_utils.get_size(dev)})
- block_devices.clear()
-
-
-# This method discovers only Intel SSD devices
-def discover_ssd_devices(block_devices, devices_res):
- ssd_count = int(TestRun.executor.run_expect_success(
- 'intelmas show -intelssd | grep DevicePath | wc -l').stdout)
- for i in range(0, ssd_count):
- # Workaround for intelmas bug that lists all of the devices (non intel included)
- # with -intelssd flag
- if TestRun.executor.run(
- f"intelmas show -display index -intelssd {i} | grep -w Intel").exit_code == 0:
- device_path = TestRun.executor.run_expect_success(
- f"intelmas show -intelssd {i} | grep DevicePath").stdout.split()[2]
- dev = device_path.replace("/dev/", "")
- if "sg" in dev:
- sata_dev = TestRun.executor.run_expect_success(
- f"sg_map | grep {dev}").stdout.split()[1]
- dev = sata_dev.replace("/dev/", "")
- if dev not in block_devices:
- continue
- serial_number = TestRun.executor.run_expect_success(
- f"intelmas show -intelssd {i} | grep SerialNumber").stdout.split()[2].strip()
- if 'nvme' not in device_path:
- disk_type = 'sata'
- device_path = dev
- elif TestRun.executor.run(
- f"intelmas show -intelssd {i} | grep Optane").exit_code == 0:
- disk_type = 'optane'
- else:
- disk_type = 'nand'
-
- devices_res.append({
- "type": disk_type,
- "path": resolve_to_by_id_link(device_path),
- "serial": serial_number,
- "blocksize": disk_utils.get_block_size(dev),
- "size": disk_utils.get_size(dev)})
- block_devices.remove(dev)
-
-
-def get_disk_serial_number(dev_path):
- commands = [
- f"(udevadm info --query=all --name={dev_path} | grep 'SCSI.*_SERIAL' || "
- f"udevadm info --query=all --name={dev_path} | grep 'ID_SERIAL_SHORT') | "
- "awk --field-separator '=' '{print $NF}'",
- f"sg_inq {dev_path} 2> /dev/null | grep '[Ss]erial number:' | "
- "awk '{print $NF}'",
- f"udevadm info --query=all --name={dev_path} | grep 'ID_SERIAL' | "
- "awk --field-separator '=' '{print $NF}'"
- ]
- for command in commands:
- serial = TestRun.executor.run(command).stdout
- if serial:
- return serial.split('\n')[0]
- return None
-
-
-def get_all_serial_numbers():
- serial_numbers = {}
- block_devices = get_block_devices_list()
- for dev in block_devices:
- serial = get_disk_serial_number(dev)
- try:
- path = resolve_to_by_id_link(dev)
- except Exception:
- continue
- if serial:
- serial_numbers[serial] = path
- else:
- TestRun.LOGGER.warning(f"Device {path} ({dev}) does not have a serial number.")
- serial_numbers[path] = path
- return serial_numbers
-
-
-def get_system_disks():
- system_device = TestRun.executor.run_expect_success('mount | grep " / "').stdout.split()[0]
- readlink_output = readlink(system_device)
- device_name = readlink_output.split('/')[-1]
- sys_block_path = os_utils.get_sys_block_path()
- used_device_names = __get_slaves(device_name)
- if not used_device_names:
- used_device_names = [device_name]
- disk_names = []
- for device_name in used_device_names:
- if check_if_file_exists(f'{sys_block_path}/{device_name}/partition'):
- parent_device = readlink(f'{sys_block_path}/{device_name}/..').split('/')[-1]
- disk_names.append(parent_device)
- else:
- disk_names.append(device_name)
-
- return disk_names
-
-
-def __get_slaves(device_name: str):
- try:
- device_names = TestRun.executor.run_expect_success(
- f'ls {os_utils.get_sys_block_path()}/{device_name}/slaves').stdout.splitlines()
- except CmdException as e:
- if "No such file or directory" not in e.output.stderr:
- raise
- return None
- device_list = []
- for device_name in device_names:
- slaves = __get_slaves(device_name)
- if slaves:
- for slave in slaves:
- device_list.append(slave)
- else:
- device_list.append(device_name)
- return device_list
-
-
-def resolve_to_by_id_link(path):
- by_id_paths = TestRun.executor.run_expect_success("ls /dev/disk/by-id -1").stdout.splitlines()
- dev_full_paths = [posixpath.join("/dev/disk/by-id", by_id_path) for by_id_path in by_id_paths]
-
- for full_path in dev_full_paths:
- # handle exception for broken links
- try:
- if readlink(full_path) == readlink(posixpath.join("/dev", path)):
- return full_path
- except CmdException:
- continue
-
- raise ValueError(f'By-id device link not found for device {path}')
diff --git a/test/functional/test-framework/test_utils/drbd.py b/test/functional/test-framework/test_utils/drbd.py
deleted file mode 100644
index bec4497..0000000
--- a/test/functional/test-framework/test_utils/drbd.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause-Clear
-#
-
-import os
-
-from test_utils.filesystem.file import File
-
-
-class Resource:
- def __init__(self, name, device, nodes, options=None):
- self.name = name
- self.device = device
- self.nodes = nodes
- self.options = options
-
- def __str__(self):
- output = (
- f"resource {self.name} {{ \n"
- f" device {self.device}; \n"
- f"{''.join([str(node) for node in self.nodes])}"
- )
-
- if self.options:
- output += f" options {{\n"
- for (k, v) in self.options.items():
- output += f" {k} {v};\n"
- output += f" }}\n"
-
- output += f"}}"
- return output
-
- def __repr__(self):
- return str(self)
-
- def save(self, path="/etc/drbd.d/", filename=None):
- filename = filename if filename else f"{self.name}.res"
- file = File(path + filename)
- file.write(str(self))
-
-
-class Node:
- def __init__(self, name, disk, meta_disk, ip, port):
- self.name = name
- self.disk = disk
- self.meta_disk = meta_disk
- self.ip = ip
- self.port = port
-
- def __str__(self):
- return (
- f" on {self.name} {{ \n"
- f" disk {self.disk};\n"
- f" meta-disk {self.meta_disk};\n"
- f" address {self.ip}:{self.port};\n"
- f" }} \n"
- )
-
- def __repr__(self):
- return str(self)
diff --git a/test/functional/test-framework/test_utils/dut.py b/test/functional/test-framework/test_utils/dut.py
deleted file mode 100644
index 0780dcb..0000000
--- a/test/functional/test-framework/test_utils/dut.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from storage_devices.disk import Disk, DiskType
-
-
-class Dut:
- def __init__(self, dut_info):
- self.config = dut_info
- self.disks = []
- for disk_info in dut_info.get('disks', []):
- self.disks.append(Disk.create_disk(disk_info['path'],
- DiskType[disk_info['type']],
- disk_info['serial'],
- disk_info['blocksize']))
- self.disks.sort(key=lambda disk: disk.disk_type, reverse=True)
-
- self.ipmi = dut_info['ipmi'] if 'ipmi' in dut_info else None
- self.spider = dut_info['spider'] if 'spider' in dut_info else None
- self.wps = dut_info['wps'] if 'wps' in dut_info else None
- self.env = dut_info['env'] if 'env' in dut_info else None
- self.ip = dut_info['ip'] if 'ip' in dut_info else "127.0.0.1"
-
- def __str__(self):
- dut_str = f'ip: {self.ip}\n'
- dut_str += f'ipmi: {self.ipmi["ip"]}\n' if self.ipmi is not None else ''
- dut_str += f'spider: {self.spider["ip"]}\n' if self.spider is not None else ''
- dut_str += f'wps: {self.wps["ip"]} port: {self.wps["port"]}\n' \
- if self.wps is not None else ''
- dut_str += f'disks:\n'
- for disk in self.disks:
- dut_str += f"\t{disk}"
- dut_str += "\n"
- return dut_str
-
- def get_disks_of_type(self, disk_type: DiskType):
- ret_list = []
- for d in self.disks:
- if d.disk_type == disk_type:
- ret_list.append(d)
- return ret_list
diff --git a/test/functional/test-framework/test_utils/emergency_escape.py b/test/functional/test-framework/test_utils/emergency_escape.py
deleted file mode 100644
index a997032..0000000
--- a/test/functional/test-framework/test_utils/emergency_escape.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from textwrap import dedent
-from string import Template
-from pathlib import Path
-
-from .systemd import enable_service, reload_daemon, systemd_service_directory, disable_service
-from test_tools.fs_utils import (
- create_file,
- write_file,
- remove,
-)
-
-
-class EmergencyEscape:
- escape_marker = "EMERGENCY_ESCAPE"
- escape_service = Path("emergency-escape.service")
- escape_service_template = Template(
- dedent(
- f"""
- [Unit]
- After=emergency.target
- IgnoreOnIsolate=true
- DefaultDependencies=no
-
- [Service]
- Type=oneshot
- ExecStart=/bin/sh -c '/usr/bin/echo "{escape_marker}" > /dev/kmsg'
- $user_method
- ExecStart=/usr/bin/systemctl daemon-reload
- ExecStart=/usr/bin/systemctl default --no-block
-
- [Install]
- WantedBy=emergency.target
- """
- ).strip()
- )
- cleanup_service = Path("emergency-escape-cleanup.service")
- cleanup_service_template = Template(
- dedent(
- """
- [Unit]
- After=emergency-escape.service
- IgnoreOnIsolate=true
- DefaultDependencies=no
-
- [Service]
- Type=oneshot
- $user_method
- ExecStart=/usr/bin/systemctl disable emergency-escape.service
- ExecStart=/usr/bin/rm -f /usr/lib/systemd/system/emergency-escape.service
- ExecStart=/usr/bin/systemctl daemon-reload
-
- [Install]
- WantedBy=emergency-escape.service
- """
- ).strip()
- )
-
- def __init__(self):
- self.escape_method = []
- self.cleanup_method = []
-
- def arm(self):
- escape_path = str(systemd_service_directory / EmergencyEscape.escape_service)
- cleanup_path = str(systemd_service_directory / EmergencyEscape.cleanup_service)
-
- create_file(escape_path)
- create_file(cleanup_path)
-
- user_escape = "\n".join([f"ExecStart={method}" for method in self.escape_method])
- user_cleanup = "\n".join([f"ExecStart={method}" for method in self.cleanup_method])
-
- escape_contents = EmergencyEscape.escape_service_template.substitute(
- user_method=user_escape
- )
- cleanup_contents = EmergencyEscape.cleanup_service_template.substitute(
- user_method=user_cleanup
- )
-
- write_file(escape_path, escape_contents)
- write_file(cleanup_path, cleanup_contents)
-
- enable_service(EmergencyEscape.escape_service)
- enable_service(EmergencyEscape.cleanup_service)
-
- def cleanup(self):
- remove(str(systemd_service_directory / EmergencyEscape.cleanup_service), ignore_errors=True)
- remove(str(systemd_service_directory / EmergencyEscape.escape_service), ignore_errors=True)
- reload_daemon()
-
- @classmethod
- def verify_trigger_in_log(cls, log_list):
- for l in log_list:
- if cls.escape_marker in l:
- return True
-
- return False
-
- def add_escape_method_command(self, method):
- self.escape_method.append(method)
-
- def add_cleanup_method_command(self, method):
- self.cleanup_method.append(method)
-
- def __enter__(self):
- self.arm()
-
- def __exit__(self, exc_type, exc_value, exc_traceback):
- self.cleanup()
diff --git a/test/functional/test-framework/test_utils/filesystem/__init__.py b/test/functional/test-framework/test_utils/filesystem/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/functional/test-framework/test_utils/filesystem/directory.py b/test/functional/test-framework/test_utils/filesystem/directory.py
deleted file mode 100644
index 7e46332..0000000
--- a/test/functional/test-framework/test_utils/filesystem/directory.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_tools.fs_utils import check_if_directory_exists
-from test_utils.filesystem.fs_item import FsItem
-
-
-class Directory(FsItem):
- def __init__(self, full_path):
- FsItem.__init__(self, full_path)
-
- def ls(self):
- output = fs_utils.ls(f"{self.full_path}")
- return fs_utils.parse_ls_output(output, self.full_path)
-
- @staticmethod
- def create_directory(path: str, parents: bool = False):
- fs_utils.create_directory(path, parents)
- output = fs_utils.ls_item(path)
- return fs_utils.parse_ls_output(output)[0]
-
- @staticmethod
- def create_temp_directory(parent_dir_path: str = "/tmp"):
- command = f"mktemp --directory --tmpdir={parent_dir_path}"
- output = TestRun.executor.run_expect_success(command)
- if not check_if_directory_exists(output.stdout):
- TestRun.LOGGER.exception("'mktemp' succeeded, but created directory does not exist")
- return Directory(output.stdout)
diff --git a/test/functional/test-framework/test_utils/filesystem/file.py b/test/functional/test-framework/test_utils/filesystem/file.py
deleted file mode 100644
index e6071e1..0000000
--- a/test/functional/test-framework/test_utils/filesystem/file.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from core.test_run import TestRun
-from test_tools import fs_utils
-from test_tools.dd import Dd
-from test_utils.filesystem.fs_item import FsItem
-from test_utils.size import Size
-
-
-class File(FsItem):
- def __init__(self, full_path):
- FsItem.__init__(self, full_path)
-
- def compare(self, other_file):
- return fs_utils.compare(str(self), str(other_file))
-
- def diff(self, other_file):
- return fs_utils.diff(str(self), str(other_file))
-
- def md5sum(self, binary=True):
- output = TestRun.executor.run(
- f"md5sum {'-b' if binary else ''} {self.full_path}")
- if output.exit_code != 0:
- raise Exception(f"Md5sum command execution failed! {output.stdout}\n{output.stderr}")
- return output.stdout.split()[0]
-
- def read(self):
- return fs_utils.read_file(str(self))
-
- def write(self, content, overwrite: bool = True):
- fs_utils.write_file(str(self), content, overwrite)
- self.refresh_item()
-
- def get_properties(self):
- return FileProperties(self)
-
- @staticmethod
- def create_file(path: str):
- fs_utils.create_file(path)
- output = fs_utils.ls_item(path)
- return fs_utils.parse_ls_output(output)[0]
-
- def padding(self, size: Size):
- dd = Dd().input("/dev/zero").output(self).count(1).block_size(size)
- dd.run()
- self.refresh_item()
-
- def remove(self, force: bool = False, ignore_errors: bool = False):
- fs_utils.remove(str(self), force=force, ignore_errors=ignore_errors)
-
- def copy(self,
- destination,
- force: bool = False,
- recursive: bool = False,
- dereference: bool = False):
- fs_utils.copy(str(self), destination, force, recursive, dereference)
- if fs_utils.check_if_directory_exists(destination):
- path = f"{destination}{'/' if destination[-1] != '/' else ''}{self.name}"
- else:
- path = destination
- output = fs_utils.ls_item(path)
- return fs_utils.parse_ls_output(output)[0]
-
-
-class FileProperties:
- def __init__(self, file):
- file = fs_utils.parse_ls_output(fs_utils.ls_item(file.full_path))[0]
- self.full_path = file.full_path
- self.parent_dir = FsItem.get_parent_dir(self.full_path)
- self.name = FsItem.get_name(self.full_path)
- self.modification_time = file.modification_time
- self.owner = file.owner
- self.group = file.group
- self.permissions = file.permissions
- self.size = file.size
-
- def __eq__(self, other):
- return (self.permissions == other.permissions and self.size == other.size
- and self.owner == other.owner and self.group == other.group
- and self.name == other.name)
diff --git a/test/functional/test-framework/test_utils/filesystem/fs_item.py b/test/functional/test-framework/test_utils/filesystem/fs_item.py
deleted file mode 100644
index c060ae3..0000000
--- a/test/functional/test-framework/test_utils/filesystem/fs_item.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import posixpath
-
-from test_tools import fs_utils
-
-
-class FsItem:
- def __init__(self, full_path):
- self.full_path = full_path
- # all below values must be refreshed in refresh_item()
- self.parent_dir = self.get_parent_dir(self.full_path)
- self.name = self.get_name(self.full_path)
- self.modification_time = None
- self.owner = None
- self.group = None
- self.permissions = FsPermissions()
- self.size = None
-
- @staticmethod
- def get_name(path):
- head, tail = posixpath.split(path)
- return tail or posixpath.basename(head)
-
- @staticmethod
- def get_parent_dir(path):
- head, tail = posixpath.split(path)
- if tail:
- return head
- else:
- head, tail = posixpath.split(head)
- return head
-
- def __str__(self):
- return self.full_path
-
- def chmod_numerical(self, permissions: int, recursive: bool = False):
- fs_utils.chmod_numerical(self.full_path, permissions, recursive)
- self.refresh_item()
-
- def chmod(self,
- permissions: fs_utils.Permissions,
- users: fs_utils.PermissionsUsers,
- sign: fs_utils.PermissionSign = fs_utils.PermissionSign.set,
- recursive: bool = False):
- fs_utils.chmod(self.full_path, permissions, users, sign=sign, recursive=recursive)
- self.refresh_item()
-
- def chown(self, owner, group, recursive: bool = False):
- fs_utils.chown(self.full_path, owner, group, recursive)
- self.refresh_item()
-
- def copy(self,
- destination,
- force: bool = False,
- recursive: bool = False,
- dereference: bool = False):
- target_dir_exists = fs_utils.check_if_directory_exists(destination)
- fs_utils.copy(str(self), destination, force, recursive, dereference)
- if target_dir_exists:
- path = f"{destination}{'/' if destination[-1] != '/' else ''}{self.name}"
- else:
- path = destination
- output = fs_utils.ls_item(f"{path}")
- return fs_utils.parse_ls_output(output)[0]
-
- def move(self,
- destination,
- force: bool = False):
- target_dir_exists = fs_utils.check_if_directory_exists(destination)
- fs_utils.move(str(self), destination, force)
- if target_dir_exists:
- self.full_path = f"{destination}{'/' if destination[-1] != '/' else ''}{self.name}"
- else:
- self.full_path = destination
- self.refresh_item()
- return self
-
- def refresh_item(self):
- updated_file = fs_utils.parse_ls_output(fs_utils.ls_item(self.full_path))[0]
- # keep order the same as in __init__()
- self.parent_dir = updated_file.parent_dir
- self.name = updated_file.name
- self.modification_time = updated_file.modification_time
- self.owner = updated_file.owner
- self.group = updated_file.group
- self.permissions = updated_file.permissions
- self.size = updated_file.size
- return self
-
-
-class FsPermissions:
- def __init__(self, user=None, group=None, other=None):
- self.user = user
- self.group = group
- self.other = other
-
- def __eq__(self, other):
- return self.user == other.user and self.group == other.group and self.other == other.other
diff --git a/test/functional/test-framework/test_utils/filesystem/symlink.py b/test/functional/test-framework/test_utils/filesystem/symlink.py
deleted file mode 100644
index e67906c..0000000
--- a/test/functional/test-framework/test_utils/filesystem/symlink.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from core.test_run import TestRun
-from test_tools.fs_utils import (
- readlink,
- create_directory,
- check_if_symlink_exists,
- check_if_directory_exists,
-)
-from test_utils.filesystem.file import File
-
-
-class Symlink(File):
- def __init__(self, full_path):
- File.__init__(self, full_path)
-
- def md5sum(self, binary=True):
- output = TestRun.executor.run_expect_success(
- f"md5sum {'-b' if binary else ''} {self.get_target()}"
- )
- return output.stdout.split()[0]
-
- def get_target(self):
- return readlink(self.full_path)
-
- def get_symlink_path(self):
- return self.full_path
-
- def remove_symlink(self):
- path = self.get_symlink_path()
- TestRun.executor.run_expect_success(f"rm -f {path}")
-
- @classmethod
- def create_symlink(cls, link_path: str, target: str, force: bool = False):
- """
- Creates a Symlink - new or overwrites existing one if force parameter is True
- :param link_path: path to the place where we want to create a symlink
- :param target: the path of an object that the requested Symlink points to
- :param force: determines if the existing symlink with the same name should be overridden
- return: Symlink object located under link_path
- """
- cmd = f"ln --symbolic {target} {link_path}"
- is_dir = check_if_directory_exists(link_path)
- parent_dir = cls.get_parent_dir(link_path)
- if is_dir:
- raise IsADirectoryError(f"'{link_path}' is an existing directory.")
- if force:
- if not check_if_directory_exists(parent_dir):
- create_directory(parent_dir, True)
- TestRun.executor.run_expect_success(f"rm -f {link_path}")
- TestRun.executor.run_expect_success(cmd)
- return cls(link_path)
-
- @classmethod
- def get_symlink(cls, link_path: str, target: str = None, create: bool = False):
- """
- Request a Symlink (create new or identify existing)
- :param link_path: full path of the requested Symlink
- :param target: path of an object that the requested Symlink points to
- (required if create is True)
- :param create: determines if the requested Symlink should be created if it does not exist
- :return: Symlink object located under link_path
- """
- if create and not target:
- raise AttributeError("Target is required for symlink creation.")
-
- is_symlink = check_if_symlink_exists(link_path)
- if is_symlink:
- if not target or readlink(link_path) == readlink(target):
- return cls(link_path)
- else:
- raise FileExistsError("Existing symlink points to a different target.")
- elif not create:
- raise FileNotFoundError("Requested symlink does not exist.")
-
- is_dir = check_if_directory_exists(link_path)
- if is_dir:
- raise IsADirectoryError(
- f"'{link_path}' is an existing directory." "\nUse a full path for symlink creation."
- )
-
- parent_dir = cls.get_parent_dir(link_path)
- if not check_if_directory_exists(parent_dir):
- create_directory(parent_dir, True)
-
- cmd = f"ln --symbolic {target} {link_path}"
- TestRun.executor.run_expect_success(cmd)
- return cls(link_path)
diff --git a/test/functional/test-framework/test_utils/fstab.py b/test/functional/test-framework/test_utils/fstab.py
deleted file mode 100644
index fceb375..0000000
--- a/test/functional/test-framework/test_utils/fstab.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from test_tools import fs_utils
-from test_utils import systemd
-
-
-def add_mountpoint(device, mount_point, fs_type, mount_now=True):
- fs_utils.append_line("/etc/fstab",
- f"{device.path} {mount_point} {fs_type.name} defaults 0 0")
- systemd.reload_daemon()
- if mount_now:
- systemd.restart_service("local-fs.target")
-
-
-def remove_mountpoint(device):
- fs_utils.remove_lines("/etc/fstab", device.path)
- systemd.reload_daemon()
diff --git a/test/functional/test-framework/test_utils/generator.py b/test/functional/test-framework/test_utils/generator.py
deleted file mode 100644
index 8c64ba6..0000000
--- a/test/functional/test-framework/test_utils/generator.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import random
-import string
-
-
-def random_string(length: int, chars=string.ascii_letters + string.digits):
- return ''.join(random.choice(chars) for i in range(length))
diff --git a/test/functional/test-framework/test_utils/io_stats.py b/test/functional/test-framework/test_utils/io_stats.py
deleted file mode 100644
index 9a3f218..0000000
--- a/test/functional/test-framework/test_utils/io_stats.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#
-# Copyright(c) 2020-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-import re
-
-from core.test_run import TestRun
-from test_utils.output import CmdException
-
-SYSFS_LINE_FORMAT = r"^(\d+\s+){10,}\d+$"
-PROCFS_LINE_FORMAT = r"^\d+\s+\d+\s+\w+\s+" + SYSFS_LINE_FORMAT[1:]
-
-
-# This class represents block device I/O statistics.
-# For more information see:
-# https://www.kernel.org/doc/Documentation/admin-guide/iostats.rst
-class IoStats:
- def __init__(self):
- self.reads = None # field 0
- self.reads_merged = None # field 1
- self.sectors_read = None # field 2
- self.read_time_ms = None # field 3
- self.writes = None # field 4
- self.writes_merged = None # field 5
- self.sectors_written = None # field 6
- self.write_time_ms = None # field 7
- self.ios_in_progress = None # field 8
- self.io_time_ms = None # field 9
- self.io_time_weighed_ms = None # field 10
- # only in kernels 4.18+
- self.discards = None # field 11
- self.discards_merged = None # field 12
- self.sectors_discarded = None # field 13
- self.discard_time_ms = None # field 14
- # only in kernels 5.5+
- self.flushes = None # field 15
- self.flush_time_ms = None # field 16
-
- def __sub__(self, other):
- if self.reads < other.reads:
- raise Exception("Cannot subtract Reads")
- if self.writes < other.writes:
- raise Exception("Cannot subtract Writes")
-
- stats = IoStats()
- stats.reads = self.reads - other.reads
- stats.reads_merged = self.reads_merged - other.reads_merged
- stats.sectors_read = self.sectors_read - other.sectors_read
- stats.read_time_ms = self.read_time_ms - other.read_time_ms
- stats.writes = self.writes - other.writes
- stats.writes_merged = self.writes_merged - other.writes_merged
- stats.sectors_written = self.sectors_written - other.sectors_written
- stats.write_time_ms = self.write_time_ms - other.write_time_ms
- stats.ios_in_progress = 0
- stats.io_time_ms = self.io_time_ms - other.io_time_ms
- stats.io_time_weighed_ms = self.io_time_weighed_ms - other.io_time_weighed_ms
- if stats.discards and other.discards:
- stats.discards = self.discards - other.discards
- if stats.discards_merged and other.discards_merged:
- stats.discards_merged = self.discards_merged - other.discards_merged
- if stats.sectors_discarded and other.sectors_discarded:
- stats.sectors_discarded = self.sectors_discarded - other.sectors_discarded
- if stats.discard_time_ms and other.discard_time_ms:
- stats.discard_time_ms = self.discard_time_ms - other.discard_time_ms
- if stats.flushes and other.flushes:
- stats.flushes = self.flushes - other.flushes
- if stats.flush_time_ms and other.flush_time_ms:
- stats.flush_time_ms = self.flush_time_ms - other.flush_time_ms
- return stats
-
- @staticmethod
- def parse(stats_line: str):
- stats_line = stats_line.strip()
-
- if re.match(SYSFS_LINE_FORMAT, stats_line):
- fields = stats_line.split()
- elif re.match(PROCFS_LINE_FORMAT, stats_line):
- fields = stats_line.split()[3:]
- else:
- raise Exception(f"Wrong input format for diskstat parser")
-
- values = [int(f) for f in fields]
-
- stats = IoStats()
- stats.reads = values[0]
- stats.reads_merged = values[1]
- stats.sectors_read = values[2]
- stats.read_time_ms = values[3]
- stats.writes = values[4]
- stats.writes_merged = values[5]
- stats.sectors_written = values[6]
- stats.write_time_ms = values[7]
- stats.ios_in_progress = values[8]
- stats.io_time_ms = values[9]
- stats.io_time_weighed_ms = values[10]
- if len(values) > 11:
- stats.discards = values[11]
- stats.discards_merged = values[12]
- stats.sectors_discarded = values[13]
- stats.discard_time_ms = values[14]
- if len(values) > 15:
- stats.flushes = values[15]
- stats.flush_time_ms = values[16]
- return stats
-
- @staticmethod
- def get_io_stats(device_id):
- stats_output = TestRun.executor.run_expect_success(
- f"cat /proc/diskstats | grep '{device_id} '")
- if not stats_output.stdout.strip():
- raise CmdException("Failed to get statistics for device " + device_id, stats_output)
- return IoStats.parse(stats_line=stats_output.stdout.splitlines()[0])
diff --git a/test/functional/test-framework/test_utils/linux_command.py b/test/functional/test-framework/test_utils/linux_command.py
deleted file mode 100644
index b6d887b..0000000
--- a/test/functional/test-framework/test_utils/linux_command.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from collections import defaultdict
-
-
-class LinuxCommand:
- def __init__(self, command_executor, command_name):
- self.command_executor = command_executor
- self.command_param = defaultdict(list)
- self.command_flags = []
- self.command_name = command_name
- self.param_name_prefix = ''
- self.param_separator = ' '
- self.param_value_prefix = '='
- self.param_value_list_separator = ','
- self.command_env_var = defaultdict(list)
- self.env_var_separator = ' '
- self.env_var_value_prefix = '='
-
- def run(self):
- return self.command_executor.run(str(self))
-
- def run_in_background(self):
- return self.command_executor.run_in_background(str(self))
-
- def set_flags(self, *flag):
- for f in flag:
- self.command_flags.append(f)
- return self
-
- def remove_flag(self, flag):
- if flag in self.command_flags:
- self.command_flags.remove(flag)
- return self
-
- def set_param(self, key, *values):
- self.remove_param(key)
-
- for val in values:
- self.command_param[key].append(str(val))
- return self
-
- def remove_param(self, key):
- if key in self.command_param:
- del self.command_param[key]
- return self
-
- def set_env_var(self, key, *values):
- self.remove_env_var(key)
-
- for val in values:
- self.command_env_var[key].append(str(val))
- return self
-
- def remove_env_var(self, key):
- if key in self.command_env_var:
- del self.command_env_var[key]
- return self
-
- def get_parameter_value(self, param_name):
- if param_name in self.command_param.keys():
- return self.command_param[param_name]
- return None
-
- def __str__(self):
- command = ''
- for key, value in self.command_env_var.items():
- command += f'{key}{self.env_var_value_prefix}{",".join(value)}' \
- f'{self.env_var_separator}'
- command += self.command_name
- for key, value in self.command_param.items():
- command += f'{self.param_separator}{self.param_name_prefix}' \
- f'{key}{self.param_value_prefix}{",".join(value)}'
- for flag in self.command_flags:
- command += f'{self.param_separator}{self.param_name_prefix}{flag}'
- return command
diff --git a/test/functional/test-framework/test_utils/os_utils.py b/test/functional/test-framework/test_utils/os_utils.py
deleted file mode 100644
index 8d68662..0000000
--- a/test/functional/test-framework/test_utils/os_utils.py
+++ /dev/null
@@ -1,462 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import math
-import posixpath
-import re
-import time
-from datetime import timedelta, datetime
-
-from aenum import IntFlag, Enum, IntEnum
-from packaging import version
-
-from core.test_run import TestRun
-from storage_devices.device import Device
-from test_tools.dd import Dd
-from test_tools.disk_utils import get_sysfs_path
-from test_tools.fs_utils import check_if_directory_exists, create_directory, check_if_file_exists
-from test_utils.filesystem.file import File
-from test_utils.output import CmdException
-from test_utils.retry import Retry
-from test_utils.size import Size, Unit
-
-DEBUGFS_MOUNT_POINT = "/sys/kernel/debug"
-MEMORY_MOUNT_POINT = "/mnt/memspace"
-
-
-class DropCachesMode(IntFlag):
- PAGECACHE = 1
- SLAB = 2
- ALL = PAGECACHE | SLAB
-
-
-class OvercommitMemoryMode(Enum):
- DEFAULT = 0
- ALWAYS = 1
- NEVER = 2
-
-
-class Runlevel(IntEnum):
- """
- Halt the system.
- SysV Runlevel: 0
- systemd Target: runlevel0.target, poweroff.target
- """
- runlevel0 = 0
- poweroff = runlevel0
-
- """
- Single user mode.
- SysV Runlevel: 1, s, single
- systemd Target: runlevel1.target, rescue.target
- """
- runlevel1 = 1
- rescue = runlevel1
-
- """
- User-defined/Site-specific runlevels. By default, identical to 3.
- SysV Runlevel: 2, 4
- systemd Target: runlevel2.target, runlevel4.target, multi-user.target
- """
- runlevel2 = 2
-
- """
- Multi-user, non-graphical. Users can usually login via multiple consoles or via the network.
- SysV Runlevel: 3
- systemd Target: runlevel3.target, multi-user.target
- """
- runlevel3 = 3
- multi_user = runlevel3
-
- """
- Multi-user, graphical. Usually has all the services of runlevel 3 plus a graphical login.
- SysV Runlevel: 5
- systemd Target: runlevel5.target, graphical.target
- """
- runlevel5 = 5
- graphical = runlevel5
-
- """
- Reboot
- SysV Runlevel: 6
- systemd Target: runlevel6.target, reboot.target
- """
- runlevel6 = 6
- reboot = runlevel6
-
- """
- Emergency shell
- SysV Runlevel: emergency
- systemd Target: emergency.target
- """
- runlevel7 = 7
- emergency = runlevel7
-
-
-class SystemManagerType(Enum):
- sysv = 0
- systemd = 1
-
-
-def get_system_manager():
- output = TestRun.executor.run_expect_success("ps -p 1").stdout
- type = output.split('\n')[1].split()[3]
- if type == "init":
- return SystemManagerType.sysv
- elif type == "systemd":
- return SystemManagerType.systemd
- raise Exception(f"Unknown system manager type ({type}).")
-
-
-def change_runlevel(runlevel: Runlevel):
- if runlevel == get_runlevel():
- return
- if Runlevel.runlevel0 < runlevel < Runlevel.runlevel6:
- system_manager = get_system_manager()
- if system_manager == SystemManagerType.systemd:
- TestRun.executor.run_expect_success(f"systemctl set-default {runlevel.name}.target")
- else:
- TestRun.executor.run_expect_success(
- f"sed -i 's/^.*id:.*$/id:{runlevel.value}:initdefault: /' /etc/inittab")
- TestRun.executor.run_expect_success(f"init {runlevel.value}")
-
-
-def get_runlevel():
- system_manager = get_system_manager()
- if system_manager == SystemManagerType.systemd:
- result = TestRun.executor.run_expect_success("systemctl get-default")
- try:
- name = result.stdout.split(".")[0].replace("-", "_")
- return Runlevel[name]
- except Exception:
- raise Exception(f"Cannot parse '{result.output}' to runlevel.")
- else:
- result = TestRun.executor.run_expect_success("runlevel")
- try:
- split_output = result.stdout.split()
- runlevel = Runlevel(int(split_output[1]))
- return runlevel
- except Exception:
- raise Exception(f"Cannot parse '{result.output}' to runlevel.")
-
-
-class Udev(object):
- @staticmethod
- def enable():
- TestRun.LOGGER.info("Enabling udev")
- TestRun.executor.run_expect_success("udevadm control --start-exec-queue")
-
- @staticmethod
- def disable():
- TestRun.LOGGER.info("Disabling udev")
- TestRun.executor.run_expect_success("udevadm control --stop-exec-queue")
-
- @staticmethod
- def trigger():
- TestRun.executor.run_expect_success("udevadm trigger")
-
- @staticmethod
- def settle():
- TestRun.executor.run_expect_success("udevadm settle")
-
-
-def drop_caches(level: DropCachesMode = DropCachesMode.ALL):
- TestRun.executor.run_expect_success(
- f"echo {level.value} > /proc/sys/vm/drop_caches")
-
-
-def disable_memory_affecting_functions():
- """Disables system functions affecting memory"""
- # Don't allow sshd to be killed in case of out-of-memory:
- TestRun.executor.run(
- "echo '-1000' > /proc/`cat /var/run/sshd.pid`/oom_score_adj"
- )
- TestRun.executor.run(
- "echo -17 > /proc/`cat /var/run/sshd.pid`/oom_adj"
- ) # deprecated
- TestRun.executor.run_expect_success(
- f"echo {OvercommitMemoryMode.NEVER.value} > /proc/sys/vm/overcommit_memory"
- )
- TestRun.executor.run_expect_success("echo '100' > /proc/sys/vm/overcommit_ratio")
- TestRun.executor.run_expect_success(
- "echo '64 64 32' > /proc/sys/vm/lowmem_reserve_ratio"
- )
- TestRun.executor.run_expect_success("swapoff --all")
- drop_caches(DropCachesMode.SLAB)
-
-
-def defaultize_memory_affecting_functions():
- """Sets default values to system functions affecting memory"""
- TestRun.executor.run_expect_success(
- f"echo {OvercommitMemoryMode.DEFAULT.value} > /proc/sys/vm/overcommit_memory"
- )
- TestRun.executor.run_expect_success("echo 50 > /proc/sys/vm/overcommit_ratio")
- TestRun.executor.run_expect_success(
- "echo '256 256 32' > /proc/sys/vm/lowmem_reserve_ratio"
- )
- TestRun.executor.run_expect_success("swapon --all")
-
-
-def get_free_memory():
- """Returns free amount of memory in bytes"""
- output = TestRun.executor.run_expect_success("free -b")
- output = output.stdout.splitlines()
- for line in output:
- if 'free' in line:
- index = line.split().index('free') + 1 # 1st row has 1 element less than following rows
- if 'Mem' in line:
- mem_line = line.split()
-
- return Size(int(mem_line[index]))
-
-
-def get_mem_available():
- """Returns amount of available memory from /proc/meminfo"""
- cmd = "cat /proc/meminfo | grep MemAvailable | awk '{ print $2 }'"
- mem_available = TestRun.executor.run(cmd).stdout
-
- return Size(int(mem_available), Unit.KibiByte)
-
-
-def get_module_mem_footprint(module_name):
- """Returns allocated size of specific module's metadata from /proc/vmallocinfo"""
- cmd = f"cat /proc/vmallocinfo | grep {module_name} | awk '{{ print $2 }}' "
- output_lines = TestRun.executor.run(cmd).stdout.splitlines()
- memory_used = 0
- for line in output_lines:
- memory_used += int(line)
-
- return Size(memory_used)
-
-
-def allocate_memory(size: Size):
- """Allocates given amount of memory"""
- mount_ramfs()
- TestRun.LOGGER.info(f"Allocating {size.get_value(Unit.MiB):0.2f} MiB of memory.")
- bs = Size(1, Unit.Blocks512)
- dd = (
- Dd()
- .block_size(bs)
- .count(math.ceil(size / bs))
- .input("/dev/zero")
- .output(f"{MEMORY_MOUNT_POINT}/data")
- )
- output = dd.run()
- if output.exit_code != 0:
- raise CmdException("Allocating memory failed.", output)
-
-
-def get_number_of_processors_from_cpuinfo():
- """Returns number of processors (count) which are listed out in /proc/cpuinfo"""
- cmd = f"cat /proc/cpuinfo | grep processor | wc -l"
- output = TestRun.executor.run(cmd).stdout
-
- return int(output)
-
-
-def get_number_of_processes(process_name):
- cmd = f"ps aux | grep {process_name} | grep -v grep | wc -l"
- output = TestRun.executor.run(cmd).stdout
-
- return int(output)
-
-
-def mount_ramfs():
- """Mounts ramfs to enable allocating memory space"""
- if not check_if_directory_exists(MEMORY_MOUNT_POINT):
- create_directory(MEMORY_MOUNT_POINT)
- if not is_mounted(MEMORY_MOUNT_POINT):
- TestRun.executor.run_expect_success(f"mount -t ramfs ramfs {MEMORY_MOUNT_POINT}")
-
-
-def unmount_ramfs():
- """Unmounts ramfs and releases whole space allocated by it in memory"""
- TestRun.executor.run_expect_success(f"umount {MEMORY_MOUNT_POINT}")
-
-
-def download_file(url, destination_dir="/tmp"):
- # TODO use wget module instead
- command = ("wget --tries=3 --timeout=5 --continue --quiet "
- f"--directory-prefix={destination_dir} {url}")
- TestRun.executor.run_expect_success(command)
- path = f"{destination_dir.rstrip('/')}/{File.get_name(url)}"
- return File(path)
-
-
-def get_kernel_version():
- version_string = TestRun.executor.run_expect_success("uname -r").stdout
- version_string = version_string.split('-')[0]
- return version.Version(version_string)
-
-
-class ModuleRemoveMethod(Enum):
- rmmod = "rmmod"
- modprobe = "modprobe -r"
-
-
-def is_kernel_module_loaded(module_name):
- output = TestRun.executor.run(f"lsmod | grep ^{module_name}")
- return output.exit_code == 0
-
-
-def get_sys_block_path():
- sys_block = "/sys/class/block"
- if not check_if_directory_exists(sys_block):
- sys_block = "/sys/block"
- return sys_block
-
-
-def load_kernel_module(module_name, module_args: {str, str}=None):
- cmd = f"modprobe {module_name}"
- if module_args is not None:
- for key, value in module_args.items():
- cmd += f" {key}={value}"
- return TestRun.executor.run(cmd)
-
-
-def unload_kernel_module(module_name, unload_method: ModuleRemoveMethod = ModuleRemoveMethod.rmmod):
- cmd = f"{unload_method.value} {module_name}"
- return TestRun.executor.run_expect_success(cmd)
-
-
-def get_kernel_module_parameter(module_name, parameter):
- param_file_path = f"/sys/module/{module_name}/parameters/{parameter}"
- if not check_if_file_exists(param_file_path):
- raise FileNotFoundError(f"File {param_file_path} does not exist!")
- return File(param_file_path).read()
-
-
-def is_mounted(path: str):
- if path is None or path.isspace():
- raise Exception("Checked path cannot be empty")
- command = f"mount | grep --fixed-strings '{path.rstrip('/')} '"
- return TestRun.executor.run(command).exit_code == 0
-
-
-def mount_debugfs():
- if not is_mounted(DEBUGFS_MOUNT_POINT):
- TestRun.executor.run_expect_success(f"mount -t debugfs none {DEBUGFS_MOUNT_POINT}")
-
-
-def reload_kernel_module(module_name, module_args: {str, str}=None,
- unload_method: ModuleRemoveMethod = ModuleRemoveMethod.rmmod):
- if is_kernel_module_loaded(module_name):
- unload_kernel_module(module_name, unload_method)
-
- Retry.run_while_false(
- lambda: load_kernel_module(module_name, module_args).exit_code == 0,
- timeout=timedelta(seconds=5)
- )
-
-
-def get_module_path(module_name):
- cmd = f"modinfo {module_name}"
-
- # module path is in second column of first line of `modinfo` output
- module_info = TestRun.executor.run_expect_success(cmd).stdout
- module_path = module_info.splitlines()[0].split()[1]
-
- return module_path
-
-
-def get_executable_path(exec_name):
- cmd = f"which {exec_name}"
-
- path = TestRun.executor.run_expect_success(cmd).stdout
-
- return path
-
-
-def get_udev_service_path(unit_name):
- cmd = f"systemctl cat {unit_name}"
-
- # path is in second column of first line of output
- info = TestRun.executor.run_expect_success(cmd).stdout
- path = info.splitlines()[0].split()[1]
-
- return path
-
-
-def kill_all_io():
- # TERM signal should be used in preference to the KILL signal, since a
- # process may install a handler for the TERM signal in order to perform
- # clean-up steps before terminating in an orderly fashion.
- TestRun.executor.run("killall -q --signal TERM dd fio blktrace")
- time.sleep(3)
- TestRun.executor.run("killall -q --signal KILL dd fio blktrace")
- TestRun.executor.run("kill -9 `ps aux | grep -i vdbench.* | awk '{ print $2 }'`")
-
- if TestRun.executor.run("pgrep -x dd").exit_code == 0:
- raise Exception(f"Failed to stop dd!")
- if TestRun.executor.run("pgrep -x fio").exit_code == 0:
- raise Exception(f"Failed to stop fio!")
- if TestRun.executor.run("pgrep -x blktrace").exit_code == 0:
- raise Exception(f"Failed to stop blktrace!")
- if TestRun.executor.run("pgrep vdbench").exit_code == 0:
- raise Exception(f"Failed to stop vdbench!")
-
-
-def wait(predicate, timeout: timedelta, interval: timedelta = None):
- start_time = datetime.now()
- result = False
- while start_time + timeout > datetime.now():
- result = predicate()
- if result:
- break
- if interval is not None:
- time.sleep(interval.total_seconds())
- return result
-
-
-def sync():
- TestRun.executor.run_expect_success("sync")
-
-
-def get_dut_cpu_number():
- return int(TestRun.executor.run_expect_success("nproc").stdout)
-
-
-def get_dut_cpu_physical_cores():
- """ Get list of CPU numbers that don't share physical cores """
- output = TestRun.executor.run_expect_success("lscpu --all --parse").stdout
-
- core_list = []
- visited_phys_cores = []
- for line in output.split("\n"):
- if "#" in line:
- continue
-
- cpu_no, phys_core_no = line.split(",")[:2]
- if phys_core_no not in visited_phys_cores:
- core_list.append(cpu_no)
- visited_phys_cores.append(phys_core_no)
-
- return core_list
-
-
-def set_wbt_lat(device: Device, value: int):
- if value < 0:
- raise ValueError("Write back latency can't be negative number")
-
- wbt_lat_config_path = posixpath.join(
- get_sysfs_path(device.get_device_id()), "queue/wbt_lat_usec"
- )
-
- return TestRun.executor.run_expect_success(f"echo {value} > {wbt_lat_config_path}")
-
-
-def get_wbt_lat(device: Device):
- wbt_lat_config_path = posixpath.join(
- get_sysfs_path(device.get_device_id()), "queue/wbt_lat_usec"
- )
-
- return int(TestRun.executor.run_expect_success(f"cat {wbt_lat_config_path}").stdout)
-
-
-def get_cores_ids_range(numa_node: int):
- output = TestRun.executor.run_expect_success(f"lscpu --all --parse").stdout
- parse_output = re.findall(r'(\d+),(\d+),(?:\d+),(\d+),,', output, re.I)
-
- return [element[0] for element in parse_output if int(element[2]) == numa_node]
diff --git a/test/functional/test-framework/test_utils/output.py b/test/functional/test-framework/test_utils/output.py
deleted file mode 100644
index 73e8f94..0000000
--- a/test/functional/test-framework/test_utils/output.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-class Output:
- def __init__(self, output_out, output_err, return_code):
- self.stdout = output_out.decode('utf-8', errors="ignore").rstrip() if \
- type(output_out) == bytes else output_out
- self.stderr = output_err.decode('utf-8', errors="ignore").rstrip() if \
- type(output_err) == bytes else output_err
- self.exit_code = return_code
-
- def __str__(self):
- return f"exit_code: {self.exit_code}\nstdout: {self.stdout}\nstderr: {self.stderr}"
-
-
-class CmdException(Exception):
- def __init__(self, message: str, output: Output):
- super().__init__(f"{message}\n{str(output)}")
- self.output = output
diff --git a/test/functional/test-framework/test_utils/retry.py b/test/functional/test-framework/test_utils/retry.py
deleted file mode 100644
index 10ca573..0000000
--- a/test/functional/test-framework/test_utils/retry.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright(c) 2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from datetime import datetime, timedelta
-from functools import partial
-
-from core.test_run import TestRun
-
-
-class Retry:
- """
- The Retry class implements methods designed to retry execution until desired result.
- The func parameter is meant to be a method. If this method needs args/kwargs, they should be
- encapsulated with the method, i.e. using a partial function (an example of this is contained
- within run_command_until_success())
- """
- @classmethod
- def run_command_until_success(
- cls, command: str, retries: int = None, timeout: timedelta = None
- ):
- # encapsulate method and args/kwargs as a partial function
- func = partial(TestRun.executor.run_expect_success, command)
- return cls.run_while_exception(func, retries=retries, timeout=timeout)
-
- @classmethod
- def run_while_exception(cls, func, retries: int = None, timeout: timedelta = None):
- result = None
-
- def wrapped_func():
- nonlocal result
- try:
- result = func()
- return True
- except:
- return False
-
- cls.run_while_false(wrapped_func, retries=retries, timeout=timeout)
- return result
-
- @classmethod
- def run_while_false(cls, func, retries: int = None, timeout: timedelta = None):
- if retries is None and timeout is None:
- raise AttributeError("At least one stop condition is required for Retry calls!")
- start = datetime.now()
- retry_calls = 0
- result = func()
-
- while not result:
- result = func()
- retry_calls += 1
- if result \
- or (timeout is not None and datetime.now() - start > timeout) \
- or (retries is not None and retry_calls == retries):
- break
- return result
diff --git a/test/functional/test-framework/test_utils/scsi_debug.py b/test/functional/test-framework/test_utils/scsi_debug.py
deleted file mode 100644
index d5fea09..0000000
--- a/test/functional/test-framework/test_utils/scsi_debug.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# Copyright(c) 2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import re
-
-from core.test_run import TestRun
-
-syslog_path = "/var/log/messages"
-
-
-class Logs:
- last_read_line = 1
- FLUSH = re.compile(r"scsi_debug:[\s\S]*cmd 35")
- FUA = re.compile(r"scsi_debug:[\s\S]*cmd 2a 08")
-
- @staticmethod
- def check_syslog_for_signals():
- Logs.check_syslog_for_flush()
- Logs.check_syslog_for_fua()
-
- @staticmethod
- def check_syslog_for_flush():
- """Check syslog for FLUSH logs"""
- log_lines = Logs._read_syslog(Logs.last_read_line)
- flush_logs_counter = Logs._count_logs(log_lines, Logs.FLUSH)
- log_type = "FLUSH"
- Logs._validate_logs_amount(flush_logs_counter, log_type)
-
- @staticmethod
- def check_syslog_for_fua():
- """Check syslog for FUA logs"""
- log_lines = Logs._read_syslog(Logs.last_read_line)
- fua_logs_counter = Logs._count_logs(log_lines, Logs.FUA)
- log_type = "FUA"
- Logs._validate_logs_amount(fua_logs_counter, log_type)
-
- @staticmethod
- def _read_syslog(last_read_line: int):
- """Read recent lines in syslog, mark last line and return read lines as list."""
- log_lines = TestRun.executor.run_expect_success(
- f"tail -qn +{last_read_line} {syslog_path}"
- ).stdout.splitlines()
- # mark last read line to continue next reading from here
- Logs.last_read_line += len(log_lines)
-
- return log_lines
-
- @staticmethod
- def _count_logs(log_lines: list, expected_log):
- """Count specified log in list and return its amount."""
- logs_counter = 0
-
- for line in log_lines:
- is_log_in_line = expected_log.search(line)
- if is_log_in_line is not None:
- logs_counter += 1
-
- return logs_counter
-
- @staticmethod
- def _validate_logs_amount(logs_counter: int, log_type: str):
- """Validate amount of logs and return"""
- if logs_counter == 0:
- if Logs._is_flush(log_type):
- TestRun.LOGGER.error(f"{log_type} log not occured")
- else:
- TestRun.LOGGER.warning(f"{log_type} log not occured")
- elif logs_counter == 1:
- TestRun.LOGGER.warning(f"{log_type} log occured only once.")
- else:
- TestRun.LOGGER.info(f"{log_type} log occured {logs_counter} times.")
-
- @staticmethod
- def _is_flush(log_type: str):
- return log_type == "FLUSH"
diff --git a/test/functional/test-framework/test_utils/singleton.py b/test/functional/test-framework/test_utils/singleton.py
deleted file mode 100644
index a484929..0000000
--- a/test/functional/test-framework/test_utils/singleton.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-
-class Singleton(type):
- """
- Singleton class
- """
- _instances = {}
-
- def __call__(cls, *args, **kwargs):
- if cls not in cls._instances:
- cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
- return cls._instances[cls]
diff --git a/test/functional/test-framework/test_utils/size.py b/test/functional/test-framework/test_utils/size.py
deleted file mode 100644
index 8efcedf..0000000
--- a/test/functional/test-framework/test_utils/size.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import enum
-import math
-
-from multimethod import multimethod
-
-
-def parse_unit(str_unit: str):
- for u in Unit:
- if str_unit == u.name:
- return u
-
- if str_unit == "KiB":
- return Unit.KibiByte
- elif str_unit in ["4KiB blocks", "4KiB Blocks"]:
- return Unit.Blocks4096
- elif str_unit == "MiB":
- return Unit.MebiByte
- elif str_unit == "GiB":
- return Unit.GibiByte
- elif str_unit == "TiB":
- return Unit.TebiByte
-
- if str_unit == "B":
- return Unit.Byte
- elif str_unit == "KB":
- return Unit.KiloByte
- elif str_unit == "MB":
- return Unit.MegaByte
- elif str_unit == "GB":
- return Unit.GigaByte
- elif str_unit == "TB":
- return Unit.TeraByte
-
- raise ValueError(f"Unable to parse {str_unit}")
-
-
-class Unit(enum.Enum):
- Byte = 1
- KiloByte = 1000
- KibiByte = 1024
- MegaByte = 1000 * KiloByte
- MebiByte = 1024 * KibiByte
- GigaByte = 1000 * MegaByte
- GibiByte = 1024 * MebiByte
- TeraByte = 1000 * GigaByte
- TebiByte = 1024 * GibiByte
- Blocks512 = 512
- Blocks4096 = 4096
-
- KiB = KibiByte
- KB = KiloByte
- MiB = MebiByte
- MB = MegaByte
- GiB = GibiByte
- GB = GigaByte
- TiB = TebiByte
- TB = TeraByte
-
- def get_value(self):
- return self.value
-
- def __str__(self):
- return self.get_name()
-
- def get_name(self):
- return self.name
-
- def get_short_name(self):
- if self == Unit.Byte:
- return "B"
- elif self == Unit.KibiByte:
- return "KiB"
- elif self == Unit.KiloByte:
- return "KB"
- elif self == Unit.MebiByte:
- return "MiB"
- elif self == Unit.MegaByte:
- return "MB"
- elif self == Unit.GibiByte:
- return "GiB"
- elif self == Unit.GigaByte:
- return "GB"
- elif self == Unit.TebiByte:
- return "TiB"
- elif self == Unit.TeraByte:
- return "TB"
- raise ValueError(f"Unable to get short unit name for {self}.")
-
-
-class UnitPerSecond:
- def __init__(self, unit):
- self.value = unit.get_value()
- self.name = unit.name + "/s"
-
- def get_value(self):
- return self.value
-
-
-class Size:
- def __init__(self, value: float, unit: Unit = Unit.Byte):
- if value < 0:
- raise ValueError("Size has to be positive.")
- self.value = value * unit.value
- self.unit = unit
-
- def __str__(self):
- return f"{self.get_value(self.unit)} {self.unit}"
-
- def __hash__(self):
- return self.value.__hash__()
-
- def __int__(self):
- return int(self.get_value())
-
- def __add__(self, other):
- return Size(self.get_value() + other.get_value())
-
- def __lt__(self, other):
- return self.get_value() < other.get_value()
-
- def __le__(self, other):
- return self.get_value() <= other.get_value()
-
- def __eq__(self, other):
- return self.get_value() == other.get_value()
-
- def __ne__(self, other):
- return self.get_value() != other.get_value()
-
- def __gt__(self, other):
- return self.get_value() > other.get_value()
-
- def __ge__(self, other):
- return self.get_value() >= other.get_value()
-
- def __radd__(self, other):
- return Size(other + self.get_value())
-
- def __sub__(self, other):
- if self < other:
- raise ValueError("Subtracted value is too big. Result size cannot be negative.")
- return Size(self.get_value() - other.get_value())
-
- @multimethod
- def __mul__(self, other: int):
- return Size(math.ceil(self.get_value() * other))
-
- @multimethod
- def __rmul__(self, other: int):
- return Size(math.ceil(self.get_value() * other))
-
- @multimethod
- def __mul__(self, other: float):
- return Size(math.ceil(self.get_value() * other))
-
- @multimethod
- def __rmul__(self, other: float):
- return Size(math.ceil(self.get_value() * other))
-
- @multimethod
- def __truediv__(self, other):
- if other.get_value() == 0:
- raise ValueError("Divisor must not be equal to 0.")
- return self.get_value() / other.get_value()
-
- @multimethod
- def __truediv__(self, other: int):
- if other == 0:
- raise ValueError("Divisor must not be equal to 0.")
- return Size(math.ceil(self.get_value() / other))
-
- def set_unit(self, new_unit: Unit):
- new_size = Size(self.get_value(target_unit=new_unit), unit=new_unit)
-
- if new_size != self:
- raise ValueError(f"{new_unit} is not precise enough for {self}")
-
- self.value = new_size.value
- self.unit = new_size.unit
-
- return self
-
- def get_value(self, target_unit: Unit = Unit.Byte):
- return self.value / target_unit.value
-
- def is_zero(self):
- if self.value == 0:
- return True
- else:
- return False
-
- def align_up(self, alignment):
- if self == self.align_down(alignment):
- return Size(int(self))
- return Size(int(self.align_down(alignment)) + alignment)
-
- def align_down(self, alignment):
- if alignment <= 0:
- raise ValueError("Alignment must be a positive value!")
- if alignment & (alignment - 1):
- raise ValueError("Alignment must be a power of two!")
- return Size(int(self) & ~(alignment - 1))
-
- @staticmethod
- def zero():
- return Size(0)
diff --git a/test/functional/test-framework/test_utils/systemd.py b/test/functional/test-framework/test_utils/systemd.py
deleted file mode 100644
index dc4bcfd..0000000
--- a/test/functional/test-framework/test_utils/systemd.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright(c) 2019-2022 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from pathlib import Path
-
-from core.test_run import TestRun
-
-systemd_service_directory = Path("/usr/lib/systemd/system/")
-
-def enable_service(name):
- TestRun.executor.run_expect_success(f"systemctl enable {name}")
-
-
-def disable_service(name):
- TestRun.executor.run_expect_success(f"systemctl disable {name}")
-
-
-def reload_daemon():
- TestRun.executor.run_expect_success("systemctl daemon-reload")
-
-
-def restart_service(name):
- TestRun.executor.run_expect_success(f"systemctl restart {name}")
diff --git a/test/functional/test-framework/test_utils/time.py b/test/functional/test-framework/test_utils/time.py
deleted file mode 100644
index af7268f..0000000
--- a/test/functional/test-framework/test_utils/time.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright(c) 2019-2021 Intel Corporation
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-from attotime import attotimedelta
-
-
-class Time(attotimedelta):
- def total_microseconds(self):
- return self.total_nanoseconds() / 1_000
-
- def total_milliseconds(self):
- return self.total_nanoseconds() / 1_000_000