https://github.com/com8/os-tester
A Python pip package to automate testing of whole operating systems with an image recognition based approach and libvirt (qemu). Inspired by openQA.
https://github.com/com8/os-tester
libvirt operating-system python python3 qemu testing
Last synced: 11 months ago
JSON representation
A Python pip package to automate testing of whole operating systems with an image recognition based approach and libvirt (qemu). Inspired by openQA.
- Host: GitHub
- URL: https://github.com/com8/os-tester
- Owner: COM8
- License: gpl-3.0
- Created: 2023-12-07T08:11:25.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-03-25T17:03:29.000Z (12 months ago)
- Last Synced: 2025-03-28T21:12:21.530Z (12 months ago)
- Topics: libvirt, operating-system, python, python3, qemu, testing
- Language: Python
- Homepage:
- Size: 457 KB
- Stars: 3
- Watchers: 2
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# OS Tester
A Python pip package to automate testing of whole operating systems with an image recognition based approach and libvirt (qemu). Inspired by openQA.
## Example

```python
from os_tester.vm import vm
from os_tester.stages import stages
import libvirt
# SELinux Policy for allowing Qemu to access image files:
# ausearch -c 'qemu-system-x86' --raw | audit2allow -M my-qemusystemx86
# semodule -X 300 -i my-qemusystemx86.pp
# NVME: http://blog.frankenmichl.de/2018/02/13/add-nvme-device-to-vm/
# dd if=/dev/zero of=/tmp/test_vm_1.img bs=1M count=8192
# Or:
# qemu-img create -f qcow2 /tmp/test_vm_1.qcow2 8G
def get_vm_xml(name: str, title: str, uuid: str, isoPath: str, vmImagePath: str) -> str:
ramGiB: int = 2
numCpus: int = 2
return f"""
{name}
{uuid}
{title}
{ramGiB}
{ramGiB}
{numCpus}
hvm
destroy
restart
restart
/usr/bin/qemu-system-x86_64
"""
if __name__ == "__main__":
# Connect to qemu
conn: libvirt.virConnect = libvirt.open("qemu:///system")
uuid: str = "1e6cae9f-41d7-4fca-8033-fbd538a65173" # Replace with your (random?) UUID
vmObj: vm = vm(conn, uuid, debugPlt=False)
# Delete eventually existing VMs
if vmObj.try_load():
print(f"Deleting existing VM for UUID '{uuid}'...")
vmObj.destroy()
exit(0)
print(f"VM destroyed.")
else:
print(f"No existing VM found for UUID '{uuid}'.")
# Create and start a new VM
vmXml: str = get_vm_xml(
"test_vm_1",
"Test_VM_1",
uuid,
"",
"test_vm_1.qcow2", # qemu-img create -f qcow2 test_vm_1.qcow2 8G
)
vmObj.create(vmXml)
# Load stages automation.
# We expect the `stages.yml` and referenced files inside the stages directory.
basePath: str = "stages"
stagesObj: stages = stages(basePath)
print(stagesObj)
vmObj.run_stages(stagesObj)
print("All stages done. Exiting...")
conn.close()
exit(0)
```
### Stages
Stages are defined as a YAML file. The schema for it is available under [`stages_schema.yml`](stages_schema.yml).
The following shows an example of such a file:
```yaml
stages:
- stage: Bootloader Selection
timeout_s: 15
paths:
- path:
check:
file: 0.png
mse_leq: 0.1
ssim_geq: 0.99
actions:
- keyboard_key:
value: up
duration_s: 0.25
- keyboard_key:
value: ret
duration_s: 0.25
nextStage: Installation Started
- path:
check:
file: 0_1.png
mse_leq: 0.1
ssim_geq: 0.99
actions:
- keyboard_key:
value: up
duration_s: 0.25
- keyboard_key:
value: up
duration_s: 0.25
- keyboard_key:
value: ret
duration_s: 0.25
nextStage: Installation Started
- stage: Installation Started
timeout_s: 600
paths:
- path:
check:
file: 1.png
mse_leq: 0.1
ssim_geq: 0.99
actions:
- keyboard_key:
value: up
duration_s: 0.25
nextStage: Installation Complete
- stage: Installation Complete
timeout_s: 600
paths:
- path:
check:
file: 2.png
mse_leq: 0.1
ssim_geq: 0.99
actions:
- keyboard_key:
value: tab
duration_s: 0.25
- keyboard_key:
value: tab
duration_s: 0.25
- keyboard_key:
value: ret
duration_s: 0.25
nextStage: Enter LUKS Password
- stage: Enter LUKS Password
timeout_s: 600
paths:
- path:
check:
file: 3.png
mse_leq: 0.1
ssim_geq: 0.99
actions:
- keyboard_text:
value: something
duration_s: 0.25
- keyboard_key:
value: ret
duration_s: 0.25
nextStage: None
```
## Building the pip-Package
To build the pip package run:
```bash
rm -rf dist/
python3 -m build
```
The output is then available inside the `dist/` directory.
## Upload
```bash
twine upload dist/*
```
## pre-commit
Before committing you have to run `pre-commit` to check for linting and type errors.
For this first install `pre-commit`.
```bash
dnf install pre-commit
pre-commit install
```
To run `pre-commit` manually run:
```bash
pre-commit run --all-files
```