tmt.steps.execute package
Submodules
tmt.steps.execute.internal module
- class tmt.steps.execute.internal.ExecuteInternal(**kwargs: Any)
Bases:
ExecutePlugin[ExecuteInternalData]Use the internal tmt executor to execute tests
The internal tmt executor runs tests on the guest one by one, shows testing progress and supports interactive debugging as well. Test result is based on the script exit code (for shell tests) or the results file (for beakerlib tests).
Store plugin name, data and parent step
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- data: ExecuteInternalData
- essential_requires() list[DependencySimple | DependencyFmfId | DependencyFile]
Collect all essential requirements of the plugin.
Essential requirements of a plugin are necessary for the plugin to perform its basic functionality.
- Returns:
a list of requirements.
- execute(*, invocation: TestInvocation, extra_environment: Environment | None = None, logger: Logger) list[Result]
Run test on the guest
- go(*, guest: Guest, environment: Environment | None = None, logger: Logger) None
Execute available tests
- class tmt.steps.execute.internal.ExecuteInternalData(name: str, how: str, order: int = 50, summary: Optional[str] = None, where: list[str] = <factory>, duration: str = '1h', exit_first: bool = False, script: list[tmt.utils.ShellScript] = <factory>, interactive: bool = False, no_progress_bar: bool = False)
Bases:
ExecuteStepData- interactive: bool = False
- no_progress_bar: bool = False
- script: list[ShellScript]
- to_spec() dict[str, Any]
Convert to a form suitable for saving in a specification file
- tmt.steps.execute.internal.TEST_PIDFILE_ROOT = Path('/var/tmp')
The default directory for storing test pid file.
- tmt.steps.execute.internal.TEST_WRAPPER_FILENAME_TEMPLATE = 'tmt-test-wrapper.sh-{{ INVOCATION.test.pathless_safe_name }}-{{ INVOCATION.test.serial_number }}'
A template for the shell wrapper in which the test script is saved.
It is passed to
tmt.utils.safe_filename(), but includes also test name and serial number to make it unique even among all test wrappers. See https://github.com/teemtee/tmt/issues/2997 for issue motivating the inclusion, it seems to be a good idea to prevent accidental reuse in general.
- class tmt.steps.execute.internal.UpdatableMessage(plugin: ExecuteInternal)
Bases:
UpdatableMessageUpdatable message suitable for plan progress reporting.
Based on
tmt.utils.UpdatableMessage, simplifies reporting of plan progress, namely by extracting necessary setup parameters from the plugin.Updatable message suitable for progress-bar-like reporting.
with UpdatableMessage('foo') as message: while ...: ... # check state of remote request, and update message state = remote_api.check() message.update(state)
- Parameters:
key – a string to use as the left-hand part of logged message.
enabled – if unset, no output would be performed.
indent_level – desired indentation level.
key_color – optional color to apply to
key.default_color – optional color to apply to value when
update()is called withcolorleft out.clear_on_exit – if set, the message area would be cleared when leaving the progress bar when used as a context manager.
- update(progress: str, test_name: str) None
Update progress message.
- Parameters:
value – new message to update message area with.
color – optional message color.
- tmt.steps.execute.internal.effective_pidfile_root() Path
Find out what the actual pidfile directory is.
If
TMT_TEST_PIDFILE_ROOTvariable is set, it is used. Otherwise,TEST_PIDFILE_ROOTis picked.
tmt.steps.execute.upgrade module
- class tmt.steps.execute.upgrade.ExecuteUpgrade(**kwargs: Any)
Bases:
ExecuteInternalPerform system upgrade during testing.
The upgrade executor runs the discovered tests (using the internal executor), then performs a set of upgrade tasks from a remote repository, and finally, re-runs the tests on the upgraded guest.
The
IN_PLACE_UPGRADEenvironment variable is set during the test execution to differentiate between the stages of the test. It is set tooldduring the first execution andnewduring the second execution. Test names are prefixed with this value to make the names unique.The upgrade tasks performing the actual system upgrade are taken from a remote repository either based on an upgrade path (e.g.
fedora35to36) or filters. The upgrade path must correspond to a plan name in the remote repository whose discover step selects tests (upgrade tasks) performing the upgrade. Currently, selection of upgrade tasks in the remote repository can be done using both fmf and shell discover method. The supported keys in discover are:reffilterexcludeteststest
The environment variables defined in the remote upgrade path plan are passed to the upgrade tasks when they are executed. An example of an upgrade path plan (in the remote repository):
discover: # Selects appropriate upgrade tasks (L1 tests) how: fmf filter: "tag:fedora" environment: # This is passed to upgrade tasks SOURCE: 35 TARGET: 36 execute: how: tmt
If no upgrade path is specified in the plan, the tests (upgrade tasks) are selected based on the configuration of the upgrade plugin (e.g. based on the filter in its configuration).
If these two possible ways of specifying upgrade tasks are combined, the remote discover plan is used but its options are overridden with the values specified locally.
The same options and config keys and values can be used as in the internal executor.
Minimal execute config example with an upgrade path:
execute: how: upgrade url: https://github.com/teemtee/upgrade upgrade-path: /paths/fedora35to36
Execute config example without an upgrade path:
execute: how: upgrade url: https://github.com/teemtee/upgrade filter: "tag:fedora"
Store plugin name, data and parent step
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- data: ExecuteUpgradeData
- property discover: Discover | DiscoverFmf
Return discover plugin instance
- go(*, guest: Guest, environment: Environment | None = None, logger: Logger) None
Execute available tests
- class tmt.steps.execute.upgrade.ExecuteUpgradeData(name: str, how: str, order: int = 50, summary: Optional[str] = None, where: list[str] = <factory>, duration: str = '1h', exit_first: bool = False, script: list[tmt.utils.ShellScript] = <factory>, interactive: bool = False, no_progress_bar: bool = False, url: Optional[str] = None, upgrade_path: Optional[str] = None, ref: Optional[str] = None, test: list[str] = <factory>, filter: list[str] = <factory>, exclude: list[str] = <factory>)
Bases:
ExecuteInternalData- exclude: list[str]
- filter: list[str]
- ref: str | None = None
- test: list[str]
- upgrade_path: str | None = None
- url: str | None = None
Module contents
- tmt.steps.execute.DEFAULT_SCRIPTS_DEST_DIR = Path('/usr/local/bin')
The default scripts destination directory
- tmt.steps.execute.DEFAULT_SCRIPTS_DEST_DIR_OSTREE = Path('/var/lib/tmt/scripts')
The default scripts destination directory for rpm-ostree based distributions, https://github.com/teemtee/tmt/discussions/3260
- class tmt.steps.execute.Execute(*, plan: Plan, data: _RawStepData | list[_RawStepData], logger: Logger)
Bases:
StepRun tests using the specified executor
Initialize execute step data
- DEFAULT_HOW: str = 'tmt'
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- cli_invocations: list['tmt.cli.CliInvocation'] = []
- go(force: bool = False) None
Execute tests
- load() None
Load test results
- results() list[Result]
Results from executed tests
Return a dictionary with test results according to the spec: https://tmt.readthedocs.io/en/latest/spec/plans.html#execute
- results_for_tests(tests: list[Test]) list[tuple[Result | None, Test | None]]
Collect results and corresponding tests.
- Returns:
a list of result and test pairs. * if there is not test found for the result, e.g. when results were loaded from storage but tests were not,
Nonerepresents the missing test:(result, None). * if there is no result for a test, e.g. when the test was not executed,Nonerepresents the missing result:(None, test).
- save() None
Save test results to the workdir
- summary() None
Give a concise summary of the execution
- wake() None
Wake up the step (process workdir and command line)
- class tmt.steps.execute.ExecutePlugin(*, step: Step, data: ExecuteStepDataT, workdir: Literal[True] | Path | None = None, logger: Logger)
Bases:
Plugin[ExecuteStepDataT,None]Common parent of execute plugins
Store plugin name, data and parent step
- classmethod base_command(usage: str, method_class: type[Command] | None = None) Command
Create base click command (common for all execute plugins)
- check_abort_file(invocation: TestInvocation) bool
Check for an abort file created by tmt-abort
Returns whether an abort file is present (i.e. abort occurred).
- cli_invocation: 'tmt.cli.CliInvocation' | None = None
- discover_phase: str | None = None
If set, plugin should run tests only from this discover phase.
- extract_custom_results(invocation: TestInvocation) list[Result]
Extract results from the file generated by the test itself
- extract_results(invocation: TestInvocation, logger: Logger) list[Result]
Check the test result
- extract_tmt_report_results(invocation: TestInvocation) list[Result]
Extract results from a file generated by
tmt-report-resultscript
- extract_tmt_report_results_restraint(invocation: TestInvocation, default_log: Path) list[Result]
Extract results from the file generated by
tmt-report-resultscript.Special, restraint-like handling is used to convert each recorded result into a standalone result.
- go(*, guest: Guest, environment: Environment | None = None, logger: Logger) None
Perform actions shared among plugins when beginning their tasks
- how: str = 'tmt'
- prepare_tests(guest: Guest, logger: Logger) list[TestInvocation]
Prepare discovered tests for testing
Check which tests have been discovered, for each test prepare the aggregated metadata in a file under the test data directory and finally return a list of discovered tests.
- run_checks_after_test(*, invocation: TestInvocation, environment: Environment | None = None, logger: Logger) list[CheckResult]
- run_checks_before_test(*, invocation: TestInvocation, environment: Environment | None = None, logger: Logger) list[CheckResult]
- timeout_hint(invocation: TestInvocation) None
Append a duration increase hint to the test output
- class tmt.steps.execute.ExecuteStepData(name: str, how: str, order: int = 50, summary: Optional[str] = None, where: list[str] = <factory>, duration: str = '1h', exit_first: bool = False)
Bases:
WhereableStepData,StepData- duration: str = '1h'
- exit_first: bool = False
- class tmt.steps.execute.ResultCollection(invocation: ~tmt.steps.execute.TestInvocation, filepaths: list[~tmt._compat.pathlib.Path], file_exists: bool = False, results: list[~typing.Any] = <factory>)
Bases:
objectCollection of raw results loaded from a file
- file_exists: bool = False
- filepaths: list[Path]
- invocation: TestInvocation
- results: list[Any]
- validate() None
Validate raw collected results against the result JSON schema.
Report found errors as warnings via
invocationlogger.
- tmt.steps.execute.SCRIPTS_DEST_DIR_VARIABLE = 'TMT_SCRIPTS_DIR'
The tmt environment variable name for forcing
SCRIPTS_DEST_DIR
- tmt.steps.execute.SCRIPTS_SRC_DIR = Path('/home/docs/checkouts/readthedocs.org/user_builds/tmt/envs/3398/lib/python3.13/site-packages/tmt/steps/execute/scripts')
Scripts source directory
- class tmt.steps.execute.Script(source_filename: str, destination_path: Path | None, aliases: list[str], related_variables: list[str], enabled: Callable[[Guest], bool])
Bases:
objectRepresents a script provided by the internal executor.
Must be used as a context manager. The context manager returns the source filename.
The source file is defined by the
source_filenameattribute and its location is relative to the directory specified via theSCRIPTS_SRC_DIRvariable. All scripts must be located in this directory.The default destination directory of the scripts is
DEFAULT_SCRIPTS_DEST_DIR. Onrpm-ostreedistributions like Fedora CoreOS, the default destination directory is :py:data:DEFAULT_SCRIPTS_DEST_DIR_OSTREE. The destination directory of the scripts can be forced by the script usingdestination_pathattribute.The destination directory can be overridden using the environment variable defined by the
DEFAULT_SCRIPTS_DEST_DIR_VARIABLEvariable.The
enabledattribute can specify a function which is called withGuestinstance to evaluate if the script is enabled. This can be useful to optionally disable a script for specific guests.- aliases: list[str]
- destination_path: Path | None
- source_filename: str
- class tmt.steps.execute.ScriptCreatingFile(source_filename: str, destination_path: Path | None, aliases: list[str], related_variables: list[str], enabled: Callable[[Guest], bool], created_file: str)
Bases:
ScriptRepresents a script which creates a file.
See
Scriptfor more details.- created_file: str
- class tmt.steps.execute.ScriptTemplate(source_filename: str, destination_path: Path | None, aliases: list[str], related_variables: list[str], enabled: Callable[[Guest], bool], context: dict[str, str], _rendered_script_path: Path | None = None)
Bases:
ScriptRepresents a Jinja2 templated script.
The source filename is constructed from the name of the file specified via the
source_filenameattribute, with the.j2suffix appended. The template file must be located in the directory specified viaSCRIPTS_SRC_DIRvariable.- context: dict[str, str]
- class tmt.steps.execute.TestInvocation(logger: ~tmt.log.Logger, phase: ~tmt.steps.execute.ExecutePlugin[~typing.Any], test: ~tmt.base.Test, guest: ~tmt.steps.provision.Guest, process: ~subprocess.Popen[bytes] | None = None, process_lock: ~_thread.lock = <factory>, results: list[~tmt.result.Result] = <factory>, check_results: list[~tmt.result.CheckResult] = <factory>, check_data: dict[str, ~typing.Any] = <factory>, return_code: int | None = None, start_time: str | None = None, end_time: str | None = None, real_duration: str | None = None, _restart_count: int = 0, _reboot_count: int = 0, hard_reboot_requested: bool = False)
Bases:
objectA bundle describing one test invocation.
Describes a
testinvoked on a particularguestunder the supervision of anexecutepluginphase.- property abort_request_path: Path
A path to the abort request file
- property abort_requested: bool
Whether a testing abort was requested
- check_data: dict[str, Any]
- property check_files_path: Path
Construct a directory path for check files needed by tmt
- check_results: list[CheckResult]
- end_time: str | None = None
- handle_reboot() bool
Reboot the guest if the test requested it.
Check for presence of a file signalling reboot request and orchestrate the reboot if it was requested. Also increment the
REBOOTCOUNTvariable, reset it to zero if no reboot was requested (going forward to the next test).- Returns:
Truewhen the reboot has taken place,Falseotherwise.
- handle_restart() bool
“Restart” the test if the test requested it.
Note
The test is not actually restarted, because running the test is managed by a plugin calling this method. Instead, the method performs all necessary steps before letting plugin know it should run the test once again.
Check whether a test restart was needed and allowed, and update the accounting info before letting the plugin know it’s time to run the test once again.
If requested by the test, the guest might be rebooted as well.
- Returns:
Truewhen the restart is to take place,Falseotherwise.
- hard_reboot_requested: bool = False
If set, an asynchronous observer requested a reboot while the test was running.
- property is_guest_healthy: bool
Whether the guest is deemed to be healthy and responsive.
Note
The answer is deduced from various flags set by execute code while observing the test, no additional checks are performed.
- property path: Path
Absolute path to invocation directory
- phase: ExecutePlugin[Any]
- process: Popen[bytes] | None = None
Process running the test. What binary it is depends on the guest implementation and the test, it may be, for example, a shell process, SSH process, or a
podmanprocess.
- process_lock: lock
- real_duration: str | None = None
- property reboot_request_path: Path
A path to the reboot request file
- property reboot_requested: bool
Whether a guest reboot has been requested while the test was running
- property relative_path: Path
Invocation directory path relative to step workdir
- property relative_test_data_path: Path
Test data path relative to step workdir
- property restart_requested: bool
Whether a test restart has been requested
- return_code: int | None = None
- property soft_reboot_requested: bool
If set, test requested a reboot
- start_time: str | None = None
- terminate_process(signal: Signals = Signals.SIGTERM, logger: Logger | None = None) None
Terminate the invocation process.
Warning
This method should be used carefully. Process running the invocation’s test has been started by some part of tmt code which is responsible for its well-being. Unless you have a really good reason to do so, doing things behind the tmt’s back may lead to unexpected results.
- Parameters:
signal – signal to send to the invocation process.
logger – logger to use for logging.
- property test_data_path: Path
Absolute path to test data directory
- tmt.steps.execute.effective_scripts_dest_dir(default: Path = Path('/usr/local/bin')) Path
Find out what the actual scripts destination directory is.
If the
TMT_SCRIPTS_DIRenvironment variable is set, it is used as the scripts destination directory. Otherwise, thedefaultparameter path is returned.