Compare commits

..

No commits in common. "main" and "v0.7.0" have entirely different histories.
main ... v0.7.0

108 changed files with 1339 additions and 3260 deletions

2
.github/CODEOWNERS vendored
View File

@ -2,4 +2,4 @@
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Default to all maintainers if nothing more specific matches
* @rhatdan @dougsland @yarboa @nsednev @aesteve-rh @pengshanyu @kleinffm
* @rhatdan @lsm5 @dougsland @yarboa @sandrobonazzola @nsednev @aesteve-rh @pengshanyu @kleinffm

29
.github/workflows/check-subpackages vendored Normal file
View File

@ -0,0 +1,29 @@
name: Build Subpackages
on:
pull_request
jobs:
build-subpackages:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y make
- name: Run make for each subsystem
run: |
for dir in subsystems/*; do
if [ -d "$dir" ]; then
subsystem=$(basename "$dir")
echo "Running make for $subsystem..."
make TARGETS=$subsystem subpackages
if [ $? -ne 0 ]; then
echo "❌ Make failed for $subsystem" >&2
exit 1
fi
fi
done

View File

@ -1,42 +0,0 @@
name: Build Subpackages
on:
pull_request
jobs:
build-subpackages:
runs-on: ubuntu-latest
container:
image: fedora:latest # Use Fedora as the container image
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: sudo dnf install -y git make rpmdevtools rpmbuild
- name: Run make for each subsystem
run: |
subsystem_build_failures=()
for dir in subsystems/*; do
if [ -d "$dir" ]; then
subsystem=$(basename "$dir")
echo "Running make for $subsystem..."
make TARGETS=$subsystem subpackages
if [ $? -ne 0 ]; then
subsystem_build_failures+=("$subsystem")
echo "❌ Make failed for $subsystem" >&2
fi
fi
done
if (( ${#subsystem_build_failures[@]} == 0 )); then
echo "✅ All subsystems built successfully"; \
exit 0;
else
echo "❌ The following subsystems failed to build: ";
echo -e "\t${subsystem_build_failures[@]}" | tr ' ' ', ';
exit 1;
fi

View File

@ -1,30 +0,0 @@
name: MkDocs Build Check
on:
pull_request:
paths:
- 'docs/**'
- '**.md'
jobs:
mkdocs-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install MkDocs and dependencies
run: |
pip install \
mkdocs \
mkdocs-material \
pymdown-extensions
- name: Build MkDocs site
run: mkdocs build -f docs/mkdocs.yml --strict

1
.gitignore vendored
View File

@ -6,4 +6,3 @@ qm.pp.bz2
qm_file_contexts
*.8
tests/e2e/ContainerFile.template
__pycache__/

View File

@ -45,9 +45,6 @@ jobs:
- epel-9-aarch64
- epel-9-ppc64le
- epel-9-x86_64
- epel-10-aarch64
- epel-10-ppc64le
- epel-10-x86_64
- job: tests
trigger: pull_request
@ -138,14 +135,12 @@ jobs:
dist_git_branches:
- fedora-all
- epel-9
- epel-10
- job: koji_build
trigger: commit
dist_git_branches:
- fedora-all
- epel-9
- epel-10
- job: bodhi_update
trigger: commit
@ -153,4 +148,3 @@ jobs:
# rawhide updates are created automatically
- fedora-branched
- epel-9
- epel-10

View File

@ -1,20 +0,0 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
mkdocs:
configuration: docs/mkdocs.yml
# Optionally declare the Python requirements required to build your docs
python:
install:
- requirements: docs/requirements.txt

653
README.md
View File

@ -1,58 +1,74 @@
# Topics
- [Topics](#topics)
- [QM is a containerized environment for running functional safety Quality Management software](#qm-is-a-containerized-environment-for-running-functional-safety-quality-management-software)
- [QM SELinux policy](#qm-selinux-policy)
- [BlueChi](#bluechi)
- [RPM building dependencies](#rpm-building-dependencies)
- [How OOM score adjustment is used in QM](#how-oom-score-adjustment-is-used-in-qm)
- [Priority process of OOM killer in the QM context](#priority-process-of-oom-killer-in-the-qm-context)
- [Contributing to the QM project](#contributing-to-the-qm-project)
- [Realtime](#realtime)
- [Talks and videos](#talks-and-videos)
- [RPM mirrors](#rpm-mirrors)
- [Configuring QM](#configuring-qm)
- [Modifying the `MemoryHigh` variable](#modifying-the-memoryhigh-variable)
1. [QM is a containerized environment for running Functional Safety QM (Quality Management) software](#qm-is-a-containerized-environment-for-running-functional-safety-qm-quality-management-software)
2. [SELinux Policy](#selinux-policy)
3. [BlueChi](#bluechi)
4. [RPM Building Dependencies](#rpm-building-dependencies)
5. [How the OOM Score Adjustment is Used in QM](#how-the-oom-score-adjustment-is-used-in-qm)
- [Why Use oom score adj in QM?](#why-use-oomscoreadj-in-qm)
- [OOM Score Adjustment in QM](#oom-score-adjustment-in-qm)
- [Nested Containers](#nested-containers)
- [QM Process](#qm-process)
- [ASIL Applications](#asil-applications)
- [Highlights](#highlights)
- [ASCII Diagram](#ascii-diagram)
6. [QM Sub-Packages](#qm-sub-packages)
- [Key Features of QM Sub-Packages](#key-features-of-qm-sub-packages)
- [Building QM Sub-Packages](#building-qm-sub-packages)
- [Installing QM Sub-Packages](#installing-qm-sub-packages)
- [Removing QM Sub-Packages](#removing-qm-sub-packages)
- [Creating Your Own Drop-In QM Sub-Package](#creating-your-own-drop-in-qm-sub-package)
- [QM Sub-Package ROS2](#qm-sub-package-ros2)
- [QM Sub-Package KVM](#qm-sub-package-kvm)
- [QM Sub-Package Sound](#qm-sub-package-sound)
- [QM Sub-Package Video](#qm-sub-package-video)
7. [Examples](#examples)
8. [Development](#development)
9. [Network Settings](https://github.com/containers/qm/blob/main/docs/tutorials/NETWORK.md)
10. [Realtime](#realtime)
11. [Talks and Videos](#talks-and-videos)
- [Paving the Way for Uninterrupted Car Operations - DevConf Boston 2024](https://www.youtube.com/watch?v=jTrLqpw7E6Q)
- [Security - Sample Risk Analysis according to ISO26262](https://www.youtube.com/watch?v=jTrLqpw7E6Q&t=1268s)
- [ASIL and QM - Simulation and Service Monitoring using bluechi and podman](https://www.youtube.com/watch?v=jTrLqpw7E6Q&t=1680s)
- [Containers in a Car - DevConf.CZ 2023](https://www.youtube.com/watch?v=FPxka5uDA_4)
12. [RPM Mirrors](#rpm-mirrors)
## QM is a containerized environment for running functional safety Quality Management software
## QM is a containerized environment for running Functional Safety QM (Quality Management) software
The main purpose of the Quality Management (QM) environment is to allow users to configure
an environment that prevents applications and container tools from interfering with
other processes on the system, such as in Automotive Safety Integrity Level (ASIL)
processes and applications. AutoSD is not a certified safety product. In the context of
AutoSD, QM is not for use in production environments but for research and learning purposes only.
The main purpose of this package is allow users to setup an environment which
prevents applications and container tools from interfering with other processes
on the system. For example ASIL (Automotive Safety Integrity Level) environments.
The QM environment uses containerization tools, such as cgroups, namespaces, and
security isolation, to prevent accidental interference by processes in the QM.
The QM environment uses containerization tools like cgroups, namespaces, and
security isolation to prevent accidental interference by processes in the qm.
The QM runs its own version of systemd and Podman to isolate not only the
applications and containers launched by systemd and Podman, but also systemd and
The QM will run its own version of systemd and Podman to isolate not only the
applications and containers launched by systemd and Podman but systemd and
Podman commands themselves.
This package requires the Podman package to establish the containerized
environment and uses Quadlet to set it up. Refer to the [docs directory](docs/quadlet-examples/)
for example Quadlet files.
environment and uses quadlet to set it up.
Software installed in the QM environment under `/usr/lib/qm/rootfs` is
automatically isolated from the host. To further isolate these processes
from other processes in the QM, developers can use container tools, such as Podman.
Software install into the qm environment under /usr/lib/qm/rootfs will
be automatically isolated from the host. But if developers want to further
isolate these processes from other processes in the QM they can use container
tools like Podman to further isolate.
## QM SELinux policy
## SELinux Policy
The QM SELinux policy isolates QM parts of the operating system
from the other domain-specific functional safety levels, such as ASIL.
This policy is used to isolate Quality Management parts of the operating system
from the other Domain-Specific Functional Safety Levels (ASIL).
The main purpose of this policy is to prevent applications and container
tools from interfering with other processes on the system. The QM must
isolate containers from `qm_t` processes as well as from other containers.
The main purpose of this policy is to prevent applications and container tools
with interfering with other processes on the system. The QM needs to support
further isolate containers run within the qm from the qm_t process and from
each other.
For now, all of the control processes in the QM other than containers run
with the same `qm_t` type. For more information, refer to `man qm_selinux`.
For now all of the control processes in the qm other then containers will run
with the same qm_t type.
For support with a specific SELinux issue, open a [QM issue](https://github.com/containers/qm/issues)
and include the SELinux error output from a recent QM-related operation.
The following commands yield output that can help determine the root cause of the issue:
Still would like to discuss about a specific selinux prevision?
Please open an [QM issue](https://github.com/containers/qm/issues) with the output of selinux error from a recent operation related to QM. The output of the following commands are appreciated for understanding the root cause.
```console
ausearch -m avc -ts recent | audit2why
@ -60,66 +76,444 @@ journalctl -t setroubleshoot
sealert -a /var/log/audit/audit.log
```
## BlueChi
## Bluechi
- [BlueChi](https://github.com/containers/qm/pull/57)
The package configures the bluechi-agent within the QM.
The package configures the bluechi agent within the QM.
BlueChi is a systemd service controller intended for use in highly regulated
ecosystems that feature multi-node environments with a predefined number of nodes.
Potential use cases can be found in industries that require functional safety,
such as the transportation industry in which services must be controlled across different
edge devices and where traditional orchestration tools do not comply with
BlueChi is a systemd service controller intended for multi-node environments with
a predefined number of nodes and with a focus on highly regulated ecosystems such
as those requiring functional safety. Potential use cases can be found in domains
such as transportation, where services need to be controlled across different
edge devices and where traditional orchestration tools are not compliant with
regulatory requirements.
Systems with QM installed have two systemd processes running on them. The QM
bluechi-agent is based on the hosts `/etc/bluechi/agent.conf` file. By default, any
changes to the system's `agent.conf` file are reflected in the QM `/etc/bluechi/agent.conf` file.
You can further customize the QM bluechi-agent by adding content to the
`/usr/lib/qm/rootfs/etc/bluechi/agent.conf.d/` directory.
Systems with QM installed will have two systemd's running on them. The QM bluechi-agent
is based on the hosts /etc/bluechi/agent.conf file. By default any changes to the
systems agent.conf file are reflected into the QM /etc/bluechi/agent.conf. You can
further customize the QM bluechi agent by adding content to the
/usr/lib/qm/rootfs/etc/bluechi/agent.conf.d/ directory.
```console
# dnf install -y python3-dnf-plugins-core
# dnf config-manager --set-enabled crb
```
## RPM building dependencies
## QM Sub-packages
To build QM packages on CentOS Stream 9, enable the Code Ready Builder
repository for access to the `golang-github-cpuguy83-md2man` package.
The qm project is designed to provide a flexible and modular environment for managing
Quality Management (QM) software in containerized environments. One of the key features
of the qm package is its support for sub-package(s), such as the qm-dropin sub-packages.
These sub-packages are not enabled by default and are optional. However, allow users
to easily extend or customize their QM environment by adding specific configurations,
tools, or scripts to the containerized QM ecosystem by simple installing or uninstalling
a RPM package into the system.
## How OOM score adjustment is used in QM
## Key Features of QM Sub-Packages
The Linux host kernel controls ASIL and QM processes. The Out-of-Memory (OOM) Killer is part of the Linux
kernel's memory management subsystem. OOM Killer terminates processes to release RAM in memory-constrained conditions.
The `oom_score_adj` parameter refers to the Out-of-Memory score adjustment in Linux operating systems.
The OOM Killer uses the `oom_score_adj` parameter to decide which processes to terminate when the system is
critically low on memory.
### Modularity
By fine-tuning which processes are more likely to be terminated during low-memory situations,
critical processes can be protected, which enhances the overall stability of the system.
- No configuration change, no typo or distribution rebuild/update.
- Just dnf install/remove from the tradicional rpm schema.
- For example, ASIL applications are essential to maintaining functional safety in automotive systems.
You can set their OOM score adjustment value from *-1* to *-1000*. To prioritize their operation
even in low-memory situations, setting the value to *-1000* makes the process immune to the OOM killer
and ensures that ASIL applications are the last to be terminated.
### Customizability
- The QM process has a default OOM score adjustment value set to *500*, configured via the `qm.container` file.
- Users can easily add specific configurations to enhance or modify the behavior of their QM containers.
```console
cat /usr/share/containers/systemd/qm.container | grep OOMScoreAdjust
# OOMScoreAdjust=500
### Maintainability
- Sub-packages ensure that the base qm package remains untouched, allowing easy updates without breaking custom configurations.
### Simplicity
- Like qm-dropin provide a clear directory structure and templates to guide users in customizing their QM environment.
## Building QM sub-packages
Choose one of the following sub-packages and build using make.
```bash
git clone git@github.com:containers/qm.git && cd qm
make| grep subpackage
kvm_subpackage - Creates a local RPM package, useful for development
ros2_rolling_subpackage - Creates a local RPM package, useful for development
sound_subpackage - Creates a local RPM package, useful for development
video_subpackage - Creates a local RPM package, useful for development
tty7_subpackage - Creates a local RPM package, useful for development
input_subpackage - Creates a local RPM package, useful for development
ttyUSB0_subpackage - Creates a local RPM package, useful for development
img_tempdir_subpackage - Creates a local RPM package, useful for development
windowmanager_subpackage - Creates a local RPM package, useful for development
douglas@fedora:~/qm-multiplespecs/qm$
make TARGETS=input subpackages
ls rpmbuild/RPMS/noarch/
qm-0.6.7-1.fc40.noarch.rpm qm_mount_bind_input-0.6.7-1.fc40.noarch.rpm
```
- All nested containers created inside the QM have a default OOM score adjustment of *750*.
## Installing QM sub-packages
```bash
$ sudo dnf install ./rpmbuild/RPMS/noarch/qm_mount_bind_input-0.6.7-1.fc40.noarch.rpm
<SNIP>
Complete!
```
If QM is already running, restart or reload your QM container environment to apply the new configurations.
```bash
sudo podman restart qm
```
## Removing QM sub-packages
```bash
sudo rpm -e qm_mount_bind_input
```
## QM sub-package Video
The video sub-package exposes `/dev/video0` (or many video devices required) to the container. This feature is useful for demonstrating how to share a camera from the host system into a container using Podman drop-in. To showcase this functionality, we provide the following demo:
### Building the video sub-package, installing, and restarting QM
```bash
make TARGETS=video subpackages
sudo podman restart qm
sudo dnf install ./rpmbuild/RPMS/noarch/qm_mount_bind_video-0.6.7-1.fc40.noarch.rpm
```
This simulates a rear camera when the user shifts into reverse gear.
In this simulation, we created a systemd service that, every time it is started, captures a snapshot from the webcam, simulating the action of a rear camera. (Feel free to start and restart the service multiple times!)
```bash
host> sudo podman exec -it qm bash
bash-5.2# systemctl daemon-reload
bash-5.2# systemctl start rear-camera
# ls -la /tmp/screenshot.jpg
-rw-r--r--. 1 root root 516687 Oct 13 04:05 /tmp/screenshot.jpg
bash-5.2#
```
### Copy the screenshot to the host and view it
```bash
host> sudo podman cp qm:/tmp/screenshot.jpg .
```
Great job! Now imagine all the possibilities this opens up!
## QM sub-package Sound
### Step 1: Install the QM Mount Bind Sound Package
To set up sound cards in a QM environment using Podman, follow the steps below:
Run the following commands to install the `qm_mount_bind_sound` package and restart QM (if previously in use):
```bash
# Build and install the RPM for QM sound
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=sound subpackages
sudo dnf install -y rpmbuild/RPMS/noarch/qm_mount_bind_sound-0.6.7-1.fc40.noarch.rpm
# Restart QM container (if already running)
sudo podman restart qm
### Step 2: Identify Sound Cards
After installing the drop-in and restarting QM, you need to identify which sound card in the Linux system will be used in QM. If you're familiar with your sound card setup feel free to skip this step.
To list the sound cards available on your system (in our case, we will pick the number 1):
```bash
cat /proc/asound/cards
```
**Example Output**:
```bash
0 [NVidia ]: HDA-Intel - HDA NVidia
HDA NVidia at 0x9e000000 irq 17
1 [sofhdadsp ]: sof-hda-dsp - sof-hda-dsp
LENOVO-20Y5000QUS-ThinkPadX1ExtremeGen4i
2 [USB ]: USB-Audio - USB Audio Device
Generic USB Audio at usb-0000:00:14.0-5, full speed
```
### Detecting Channels and Sample Rates
To list the supported number of channels and samples use `pactl` command:
```bash
pactl list sinks | grep -i 48000 | uniq
Sample Specification: s24-32le 2ch 48000Hz
```
### Verify Sample Rate Support
To show the supported sample rates for a specific sound card codec, you can also inspect the codec details:
```bash
cat /proc/asound/card1/codec#0 | grep -i rates
```
This will output the supported sample rates for the codec associated with `card1`.
### Differentiating Between Cards
Accessing Card 1 (sof-hda-dsp)
```bash
cat /proc/asound/cards | grep -A 1 '^ 1 '
```
Accessing Card 2 (USB Audio Device)
```bash
cat /proc/asound/cards | grep -A 1 '^ 2 '
```
### Step 3: Testing audio inside QM
Inside QM, run the following command:
```bash
podman exec -it qm bash
bash-# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76dacaa9a89e quay.io/qm-images/audio:latest sleep infinity 7 hours ago Up 7 hours systemd-audio
bash-# podman exec -it systemd-audio bash
Execute the audio test within the nested container, and the sound will be output through the physical speakers of your computer—or, in this case, the car's multimedia soundbox.
bash-# speaker-test -D hw:1,0 -c 2 -r 48000
```
Params:
```bash
hw:1,0: sound card 1, device 0
-c 2: two channels (stereo)
-r 48000: sample rate of 48 kHz
```
## Creating your own drop-in QM sub-package
We recommend using the existing drop-in files as a guide and adapting them to your specific needs. However, here are the step-by-step instructions:
1) Create a drop-in file in the directory: `etc/qm/containers/containers.conf.d`
2) Add it as a sub-package to `rpm/qm.spec`
3) Test it by running: `make clean && VERSION=YOURVERSIONHERE make rpm`
4) Additionally, test it with and without enabling the sub-package using (by default it should be disabled but there are cases where it will be enabled by default if QM community decide):
Example changing the spec and triggering the build via make (feel free to automate via sed, awk etc):
```bash
# Define the feature flag: 1 to enable, 0 to disable
# By default it's disabled: 0
%define enable_qm_dropin_img_tempdir 1
make clean && VERSION=YOURVERSIONHERE make rpm
```
## QM sub-package ROS2
The QM sub-package ROS2 (a.k.a "The Robot Operating System" or middleware for robots) is widely used by open-source projects, enterprises, companies, edge env and government agencies, including NASA, to advance robotics and autonomous systems. Enabled by Quadlet in QM, ROS2 on top of QM provides a secure environment where robots can operate and communicate safely, benefiting from QM's "Freedom from Interference" frequently tested layer. This ensures robots can function without external interference, enhancing their reliability and security.
The types of robots compatible with this environment are extensive, ranging from medical devices and aerial drones to aqua drones and space rockets. ROS2 within QM supports high availability, meaning these robotic systems can maintain continuous operations, crucial for mission-critical and industrial applications. This versatility makes it ideal for environments that demand robust communication and operational safety, from healthcare and aerospace to underwater exploration and autonomous land vehicles.
How to test this env?
```bash
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=ros2_rolling subpackages
sudo dnf install rpmbuild/RPMS/noarch/qm_ros2_rolling-0.6.7-1.fc40.noarch.rpm -y
sudo podman restart qm # if you have qm already running
Testing using talked and listener examples
$host> sudo podman exec -it qm bash
QM> ros2 run demo_nodes_cpp talker &
QM> ros2 run demo_nodes_cpp listener
```
## QM sub-package KVM
The QM sub-package KVM includes drop-in configuration that enables the integration of Kernel-based Virtual Machine (KVM) management into the QM (Quality Management) container environment. This configuration allows users to easily configure and manage KVM virtual machines within the QM system, streamlining virtualization tasks in containerized setups.
Below example step by step:
Step 1: clone QM repo, install libvirt packages, prepare some files inside QM and start the libvirt daemon.
```bash
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=kvm subpackages
sudo dnf install rpmbuild/RPMS/noarch/qm_mount_bind_kvm-0.6.7-1.fc40.noarch.rpm
sudo podman restart qm # if you have qm already running
sudo dnf --installroot /usr/lib/qm/rootfs/ install virt-install libvirt-daemon libvirt-daemon-qemu libvirt-daemon-kvm -y
# Copy default network settings to /root dir inside QM (/usr/lib/qm/rootfs/root)
$host> sudo cp /usr/share/libvirt/networks/default.xml /usr/lib/qm/rootfs/root
Step 2: Preparing cloudinit files inside QM (/usr/lib/qm/rootfs/root)
# Cloud-init files
------------------------------
$host> cd /usr/lib/qm/rootfs/root/
$host> cat meta-data
instance-id: fedora-cloud
local-hostname: fedora-vm
# We are setting to user fedora the default password as fedora
$host> cd /usr/lib/qm/rootfs/root/
$host> cat user-data
#cloud-config
password: fedora
chpasswd: { expire: False }
ssh_pwauth: True
# Download the Fedora Cloud image for tests and save it /usr/lib/qm/rootfs/var/lib/libvirt/images/
$ wget -O /usr/lib/qm/rootfs/root/Fedora-Cloud-Base-Generic.qcow2 https://download.fedoraproject.org/pub/fedora/linux/releases/40/Cloud/x86_64/images/Fedora-Cloud-Base-Generic.x86_64-40-1.14.qcow2
# Generate the cloud-init.iso and move it to /usr/lib/qm/rootfs/var/lib/libvirt/images/
$host> cloud-localds cloud-init.iso user-data meta-data
$host> mv cloud-init.iso /usr/lib/qm/rootfs/var/lib/libvirt/images/
# Change permission to qemu:qemu
$host> chown qemu:qemu /usr/lib/qm/rootfs/var/lib/libvirt/*
Step 3: Starting libvirtd and checking if it's active inside QM
##################################################################
# Keep in mind for the next steps:
# Depending on the distro you are running SELinux might complain
# about libvirtd running on QM / udev errors
##################################################################
# Going inside QM
$ sudo podman exec -it qm bash
# Starting libvirtd
bash-5.2# systemctl start libvirt
# Check if it's running:
bash-5.2# systemctl is-active libvirtd
active
```
Step 4: Creating a script inside QM and running the VM
```bash
$host> cd /usr/lib/qm/rootfs/root/
$host> vi run
##### START SCRIPT ############
# Set .cache to /tmp
export XDG_CACHE_HOME=/tmp/.cache
# Remove previous instance
virsh destroy fedora-cloud-vm 2> /dev/null
virsh undefine fedora-cloud-vm 2> /dev/null
# Network
virsh net-define ./default.xml 2> /dev/null
virsh net-start default 2> /dev/null
virsh net-autostart default 2> /dev/null
# Install
virt-install \
--name fedora-cloud-vm \
--memory 20048 \
--vcpus 4 \
--disk path=/var/lib/libvirt/images/Fedora-Cloud-Base-Generic.qcow2,format=qcow2 \
--disk path=/var/lib/libvirt/images/cloud-init.iso,device=cdrom \
--os-variant fedora-unknown \
--network network=default \
--import \
--graphics none \
--console pty,target_type=serial \
--noautoconsole
##### END SCRIPT ############
```
Step 5: Running the script
```bash
qm$ sudo podman exec -it qm bash
bash-5.2# cd /root
bash-5.2# ./run
Domain 'fedora-cloud-vm' destroyed
Domain 'fedora-cloud-vm' has been undefined
Network default marked as autostarted
Starting install...
Creating domain... | 0 B 00:00:00
Domain creation completed.
bash-5.2# virsh list
Id Name State
---------------------------------
4 fedora-cloud-vm running
bash-5.2# virsh console fedora-cloud-vm
fedora-vm login: fedora
Password:
Last login: Tue Oct 8 06:01:18 on ttyS0
[fedora@fedora-vm ~]$
```
## RPM building dependencies
In order to build qm package on CentOS Stream 9 you'll need Code Ready Builder
repository enabled in order to provide `golang-github-cpuguy83-md2man` package.
## How the OOM Score Adjustment is used in QM
The om_score_adj refers to the "Out of Memory score adjustment" in Linux operating systems. This parameter is used by the Out of Memory (OOM) killer to decide which processes to terminate when the system is critically low on memory.
### Why use oomscoreadj in QM?
By fine-tuning which processes are more likely to be terminated during low memory situations, critical processes can be protected, thereby enhancing the overall stability of the system. For instance only, ASIL (Automotive Safety Integrity Level) applications, which are critical for ensuring functional safety in automotive systems, will be preserved in case of low resources.
### OOM Score Adjustment in QM
#### Nested Containers
- All nested containers created inside QM will have their OOM score adjustment set to *750*.
```console
$ cat /usr/share/qm/containers.conf | grep oom_score_adj
oom_score_adj = 750
```
### Priority process of OOM killer in the QM context
#### QM Process
- The QM process has a default OOM score adjustment value set to *500*, configured via the *qm.container* file.
```console
cat /usr/share/containers/systemd/qm.container | grep OOMScoreAdjust
# OOMScoreAdjust=500
```
### ASIL Applications
If we consider the example of ASIL (Automotive Safety Integrity Level) applications, which are essential for maintaining functional safety in automotive systems, their OOM score adjustment values can range from -1 to -1000. Setting the value to -1000 makes the process immune to the OOM killer. This ensures that ASIL applications are the last to be terminated by the OOM killer, thus prioritizing their operation even in low memory situations.
#### Highlights
- Nested Containers inside QM: OOM score adjustment set to 750. (/usr/share/qm/containers.conf)
- QM Process: OOM score adjustment value set to 500, configured via the qm.container file.
- ASIL Applications: Can explore a range from -1 to -1000, with -1000 making the process immune to the OOM killer.
#### ASCII Diagram
```txt
+-------------------------------------------------------------+
@ -178,7 +572,7 @@ oom_score_adj = 750
| |
| Compared to other processes with the default adjustment |
| value of 0, nested containers are still more likely to be |
| terminated first, ensuring the system and ASIL apps are |
| terminated first, ensuring the system and ASIL Apps are |
| kept as safe as possible. |
| |
+-------------------------------------------------------------+
@ -188,13 +582,17 @@ oom_score_adj = 750
------------------------------------ Kernel space -----------------------------------------------
```
## Contributing to the QM project
## Examples
For information about how to contribute to the QM project, see the [Developers documentation README](docs/devel/README.md).
Looking for quadlet examples files? See our [docs dir](docs/quadlet-examples/).
## Development
If your looking for contribute to the project use our [development README guide](docs/devel/README.md) as start point.
## Realtime
To enable real-time removal of sched_* blockage via seccomp, use the following schema:
To enable real-time removal of sched_* blockage via seccomp, use the following schema.
```bash
cat << EOF >> /etc/containers/systemd/qm.container.d/rt.conf
@ -203,101 +601,14 @@ SeccompProfile=""
> EOF
```
## Talks and videos
## Talks and Videos
Let's spread the knowledge regarding QM. If you have interesting content pertaining to
QM-related technology, please share it with us.
Let's spread the knowledge regarding QM, if you have any interesting video regarding any
technology related to QM please with us.
## RPM mirrors
## RPM Mirrors
Looking for a specific version of QM? Search the [CentOS Automotive SIG Stream Mirror](https://mirror.stream.centos.org/SIGs/9-stream/automotive/aarch64/packages-main/Packages/q/). The packages in CentOS Automotive SIG Stream Mirror are for experimentation only.
Looking for a specific version of QM?
Search in the mirrors list below.
## Configuring QM
To run QM on an immutable OSTree-based OS, we use systemd units with Podman Quadlet.
For more information on how `podman-systemd.unit` works, refer to the manual:
`man podman-systemd.unit`
The default QM configuration drop-in file is located in `/usr/share/containers/systemd/qm.container`.
Modifying the original service file is not an option. Instead, create drop-in files to
modify the default configuration.
**NOTE:** The configuration is built in alphabetical order of the drop-in files.
### Modifying the `MemoryHigh` variable
To override the default settings, create a new drop-in `.conf` file in the
`/etc/containers/systemd/qm.container.d/` directory. This method ensures that QM memory
usage is controlled without modifying the base system configuration.
1. Check the current memory limit:
```bash
systemctl show -P MemoryHigh qm
infinity
```
The command output `infinity` indicates that `MemoryHigh` is unlimited. You can
see this setting in `/usr/share/containers/systemd/qm.container`.
1. Create a directory for the new drop-in file:
```bash
mkdir -p /etc/containers/systemd/qm.container.d/
```
1. Create a new drop-in file:
```bash
vim /etc/containers/systemd/qm.container.d/100-MemoryMax.conf
```
In this example, the new drop-in file is named `100-MemoryMax.conf`. You can choose a different name,
but be aware that the configuration is built in alphabetical order of the drop-in files.
1. Edit the file to add the following content:
```bash
[Service]
MemoryHigh=2G
```
`MemoryHigh` is specified in gigabytes. 2G means 2 gigabytes.
1. Preview the updated systemd configuration:
```bash
/usr/lib/systemd/system-generators/podman-system-generator {--user} --dryrun
```
1. Reload systemd and restart `qm.service` to apply the configuration changes:
```bash
systemctl daemon-reload
systemctl restart qm.service
```
1. Verify the value of `MemoryHigh`:
```bash
systemctl show -P MemoryHigh qm
2147483648
```
Memory values are displayed in bytes; 2147483648 bytes = 2G, which confirms that `MemoryHigh` is set to 2G.
[CentOS Automotive SIG - qm package - noarch](https://mirror.stream.centos.org/SIGs/9-stream/automotive/aarch64/packages-main/Packages/q/)

View File

@ -1 +1 @@
0.7.6
0.7.0

View File

@ -6,10 +6,6 @@ cgroup_conf=[
"memory.oom.group=1",
]
# Temporary default to host network until we fix private network bridge setup
# when the qm container doesn't unmask all the virtual filesystems.
netns="host"
# The om_score_adj refers to the "Out of Memory score adjustment" in Linux
# operating systems. This parameter is used by the Out of Memory (OOM)
# killer to decide which processes to terminate when the system is
@ -22,8 +18,3 @@ netns="host"
# OOMScoreAdjust=500
#
oom_score_adj = 750
[network]
# The default is 10.88.0.0, but we need qm containers to have a
# different ip address range or routing becomes confused
default_subnet="10.89.0.0/16"

View File

@ -37,69 +37,11 @@ function add_syscall_deny_list() {
local syscall_name="$1"
local seccomp_file_path="$2"
local temp_file
temp_file=$(mktemp)
if [[ "$syscall_name" == "sched_setscheduler" ]]; then
jq --tab \
'.syscalls += [
{
"names": ["sched_setscheduler"],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 1,
"value": 0,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": ["sched_setscheduler"],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 1,
"value": 3,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
},
{
"names": ["sched_setscheduler"],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 1,
"value": 5,
"valueTwo": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
}
]' "$seccomp_file_path" > "$temp_file" && mv "$temp_file" "$seccomp_file_path"
else
jq --tab \
--arg syscall "$syscall_name" \
'.syscalls += [{
"names": [$syscall],
"action": "SCMP_ACT_ERRNO",
"args": [],
"errnoRet": 1,
"errno": "EPERM"
}]' "$seccomp_file_path" > "$temp_file" && mv "$temp_file" "$seccomp_file_path"
fi
jq --tab \
--arg syscall "$syscall_name" \
'.syscalls += [{"names": [$syscall], "action": "SCMP_ACT_ERRNO", "args": [], "errnoRet": 1, "errno": "EPERM"}]' \
"${seccomp_file_path}" > "$temp_file" && mv "$temp_file" "${seccomp_file_path}"
rm "$temp_file" &> /dev/null
}

View File

@ -105,15 +105,20 @@ status() {
}
cpuweight() {
exec_color "sudo systemctl set-property --runtime QM.slice CPUWeight=50"
exec_color "sudo systemctl set-property --runtime qm.service CPUWeight=50"
echo "Value stored in qm.service/cpu.weight:"
sudo cat /sys/fs/cgroup/qm.service/cpu.weight
echo "Value stored in QM.slice/cpu.weight:"
sudo cat /sys/fs/cgroup/QM.slice/cpu.weight
exec_color "sudo systemctl set-property --runtime qm.service CPUWeight=10"
echo "Value stored in QM.slice/qm.service/cpu.weight:"
sudo cat /sys/fs/cgroup/QM.slice/qm.service/cpu.weight
exec_color "sudo systemctl set-property --runtime QM.slice CPUWeight=10"
echo "Value stored in qm.service/cpu.weight:"
sudo cat /sys/fs/cgroup/qm.service/cpu.weight
echo "Value stored in QM.slice/cpu.weight:"
sudo cat /sys/fs/cgroup/QM.slice/cpu.weight
echo "Value stored in QM.slice/qm.service/cpu.weight:"
sudo cat /sys/fs/cgroup/QM.slice/qm.service/cpu.weight
echo -e "\n\n[Press enter to continue]"
read -r
}

View File

@ -1,109 +0,0 @@
# Developers documentation
## Building QM rpm manually with changes
Building QM locally with changes for tests is a recommended practice,
especially for testing new features before submitting a pull request.
**1.** Prerequisite
```bash
dnf install -y rpm-build golang-github-cpuguy83-md2man selinux-policy-devel
```
**2.** Clone the repo
```bash
git clone https://github.com/containers/qm.git && cd qm
```
**3.** Build the RPM
Select a QM version that is a higher number from the current one.
For example, if today's QM version is 0.6.2, set it to 1.0 so that
the RPM created is identifiable as yours.
```bash
make clean && VERSION=1.0 make rpm
```
The rpm is created at the `${RPM_TOPDIR}/RPMS` folder, by default
`${PWD}/rpmbuild/RPMS`.
You can export **RPM_TOPDIR** to change the path where the rpm will be placed.
For example:
```bash
VERSION=1.0 RPM_TOPDIR=/USER/rpmbuild make rpm
```
## Building CentOS AutoSD and QM manually
During development, it is common to conduct integration tests to ensure your
changes work well with other components within the overall solution.
In our case, it's best to test against the CentOS Automotive Stream
Distribution (AutoSD) image.
Once you have the new [RPM](#building-qm-rpm-manually-with-changes), follow these steps:
**1.** Make sure the new rpm is located in **/USER/rpmbuild/RPMS/**
Example
```bash
ls /root/rpmbuild/RPMS/noarch/qm-1.0-1.noarch.rpm
/root/rpmbuild/RPMS/noarch/qm-1.0-1.noarch.rpm
```
**2.** Download additional packages required by the image
```bash
sudo dnf download --destdir /root/rpmbuild/RPMS/noarch/ selinux-policy selinux-policy-any
```
**3.** Create a local repository with the new package
```bash
dnf install createrepo_c -y
cd /root/rpmbuild/RPMS/noarch/
createrepo .
```
**4.** Clone the CentOS Automotive distro for the build
Ensure you meet the requirements for the CentOS Automotive Stream by
referring to [this link](https://sigs.centos.org/automotive/building/).
The following commands will execute:
- Install the podman package
- Clone the sample-images repository and required submodules (automotive-image-builder)
- Cleanups before a fresh build
- Finally creates a new qcow2 image (BASED ON distro name, mode (ostree or regular) and uses the qemu-qm-container sample image)
NOTE:
- The path for the new QM rpm file (/root/rpmbuild/RPMS/noarch)
- extra_rpms - useful for debug.
- ssh enabled
The command below utilises automotive-image-builder to produce a `qm-minimal` qcow2 image for cs9,
other example images such as `simple-qm-container` and the `simple-qm`
image can be found in the images directory of the sample-images repository.
```bash
dnf install podman -y && dnf clean all
git clone https://gitlab.com/CentOS/automotive/sample-images.git
git submodule update --init
cd sample-images/
rm -rf _build #Optional, only relevant after initial build
rm -rf *.qcow2 #Optional, only relevant after initial build
./automotive-image-builder/automotive-image-builder build --distro cs9 --mode package --define 'ssh_permit_root_login=true' --define 'ssh_permit_password_auth=true' --define 'extra_repos=[{"id":"local","baseurl":"file:///root/rpmbuild/RPMS/noarch"}]' --define 'extra_rpms=["qm-1.0", "vim-enhanced", "openssh-server", "openssh-clients", "python3", "polkit", "rsync", "strace", "dnf", "gdb"]' --target qemu --export qcow2 images/qm-minimal.mpp.yml cs9-qemu-qm-container.x86_64.qcow2
```
If you would like more information on building automotive images with automotive-image-builder, please see the
[Automotive SIG pages for AutoSD](https://sigs.centos.org/automotive/getting-started/about-automotive-image-builder/)
Run the virtual machine, default user: root, pass: password.
To change default values, use the [defaults.ipp.yml](https://gitlab.com/CentOS/automotive/src/automotive-image-builder/-/blob/main/include/defaults.ipp.yml) file.
```bash
./automotive-image-builder/automotive-image-runner --nographics ./cs9-qemu-qm-container.x86_64.qcow2
```

View File

@ -1,21 +0,0 @@
# Maintainer documentation
## Creating a new release
Initially, make sure to [bump **qm.te** and **VERSION** files in the git repo](https://github.com/containers/qm/pull/760) to the next release, i.e: *v0.7.5*.
After that, follow the steps below using GitHub UI.
**Create a new Release**
![Click on Releases](./pics/creatingreleases/00-Click-on-Releases.jpeg)
**Draft a new release**
![Draft a new release](./pics/creatingreleases/01-Draft-a-new-release.png)
**Create a new tag**
![Create a tag](./pics/creatingreleases/02-Create-a-tag.jpeg)
**Generate release notes**
![Generate release notes](./pics/creatingreleases/03-Generate-release-notes.jpeg)
**Publish Release**
![Click on publish release](./pics/creatingreleases/04-click-on-publish-release.jpeg)

359
docs/devel/README.md Normal file
View File

@ -0,0 +1,359 @@
# Developers documentation
## Table of contents
- [Building QM rpm manually with changes](#building-qm-rpm-manually-with-changes)
- [Building CentOS AutoSD and QM manually](#building-centos-autosd-and-qm-manually)
- [Useful Commands](#useful-commands)
- [Installing software inside QM partition](#installing-software-inside-qm-partition)
- [Removing software inside QM partition](#removing-software-inside-qm-partition)
- [Copying files to QM partition](#copying-files-to-qm-partition)
- [Listing QM service](#listing-qm-service)
- [List QM container via podman](#list-qm-container-via-podman)
- [Extend QM quadlet managed by podman](#extend-qm-quadlet-managed-by-podman)
- [Connecting to QM container via podman](#connecting-to-qm-container-via-podman)
- [SSH guest CentOS Automotive Stream Distro](#ssh-guest-centos-automotive-stream-distro)
- [Check if HOST and Container are using different network namespace](#check-if-host-and-container-are-using-different-network-namespace)
- [Debugging with podman in QM using --root](#debugging-with-podman-in-qm)
- [Creating your own drop-in QM sub-package](#creating-your-own-dropin-qm-subpackage)
- [Let automation create/publish PR sub-packages](#let-automation-create-publish-pr-subpackages)
- [Install PR copr sub-packages on local machine](#install-pr-copr-sub-packages-on-local-machine)
- [Debugging with quadlet](#debugging-with-quadlet)
## Building QM rpm manually with changes
Building QM locally with changes for tests is a recommended practice,
especially for testing new features before submitting a pull request.
**1.** Prerequisite
```bash
dnf install -y rpm-build golang-github-cpuguy83-md2man selinux-policy-devel
```
**2.** Clone the repo
```bash
git clone https://github.com/containers/qm.git
```
**3.** Build the RPM
Select a QM version that is a higher number from the current one.
For example, if today's QM version is 0.6.2, set it to 1.0 so that
the RPM created is identifiable as yours.
```bash
make clean && VERSION=1.0 make rpm
```
The rpm is created at the `${RPM_TOPDIR}/RPMS` folder, by default
`${PWD}/rpmbuild/RPMS`.
You can export **RPM_TOPDIR** to change the path where the rpm will be placed.
For example:
```bash
VERSION=1.0 RPM_TOPDIR=/USER/rpmbuild make rpm
```
## Building CentOS AutoSD and QM manually
During development, it is common to conduct integration tests to ensure your
changes work well with other components within the overall solution.
In our case, it's best to test against the CentOS Automotive Stream
Distribution (AutoSD) image.
Once you have the new [RPM](#building-qm-rpm-manually-with-changes), follow these steps:
**1.** Make sure the new rpm is located in **/USER/rpmbuild/RPMS/**
Example
```bash
ls /root/rpmbuild/RPMS/noarch/qm-1.0-1.noarch.rpm
/root/rpmbuild/RPMS/noarch/qm-1.0-1.noarch.rpm
```
**2.** Create a local repository with the new package
```bash
dnf install createrepo_c -y
cd /root/rpmbuild/RPMS/
createrepo .
```
**4.** Clone the CentOS Automotive distro for the build
Ensure you meet the requirements for the CentOS Automotive Stream by
referring to [this link](https://sigs.centos.org/automotive/building/).
The following commands will execute:
- Cleanups before a fresh build
- Remove old qcow2 images used (regular and ostree)
- Finally creates a new image (BASED ON target name, ostree or regular)
NOTE:
- The path for the new QM rpm file (/root/rpmbuild/RPMS/noarch)
- extra_rpms - useful for debug (do not use spaces between packages or will break)
- ssh enabled
```bash
dnf install podman -y && dnf clean all
git clone https://gitlab.com/CentOS/automotive/sample-images.git
git submodule update --init
cd sample-images/
rm -rf _build
rm -f cs9-qemu-qmcontainer-regular.x86_64.qcow2
rm -f cs9-qemu-qmcontainer-ostree.x86_64.qcow2
./build --distro cs9 --target qemu --define 'extra_repos=[{\"id\":\"local\",\"baseurl\":\"file:///root/rpmbuild/RPMS/noarch\"}]' --define 'extra_rpms=[\"qm-1.0\",\"vim-enhanced\",\"strace\",\"dnf\",\"gdb\",\"polkit\",\"rsync\",\"python3\",\"openssh-server\",\"openssh-clients\"]' --define 'ssh_permit_root_login=true' --define 'ssh_permit_password_auth=true' cs9-qemu-qmcontainer-regular.x86_64.qcow2
```
Run the virtual machine, default user: root, pass: password.
To change default values, use the [defaults.ipp.yml](https://gitlab.com/CentOS/automotive/src/automotive-image-builder/-/blob/main/include/defaults.ipp.yml) file.
```bash
./runvm --nographics ./cs9-qemu-qm-minimal-regular.x86_64.qcow2
```
## Useful Commands
### Installing software inside QM partition
```bash
dnf --installroot /usr/lib/qm/rootfs/ install vim -y
```
### Removing software inside QM partition
```bash
dnf --installroot /usr/lib/qm/rootfs/ remove vim -y
```
### Copying files to QM partition
Please note: This process is only applicable for regular images.
OSTree images are read-only, and any files must be included during the build process.
Once this is understood, proceed by executing the following command on the host after
the QM package has been installed.
```bash
#host> cp file_to_be_copied /usr/lib/qm/rootfs/root
#host> podman exec -it qm bash
bash-5.1> ls /root
file_to_be_copied
```
### Listing QM service
```bash
[root@localhost ~]# systemctl status qm -l
● qm.service
Loaded: loaded (/usr/share/containers/systemd/qm.container; generated)
Active: active (running) since Sun 2024-04-28 22:12:28 UTC; 12s
ago
Main PID: 354 (conmon)
Tasks: 7 (limit: 7772)
Memory: 82.1M (swap max: 0B)
CPU: 945ms
CGroup: /QM.slice/qm.service
├─libpod-payload-a83253ae278d7394cb38e975535590d71de90a41157b547040
4abd6311fd8cca
│ ├─init.scope
│ │ └─356 /sbin/init
│ └─system.slice
│ ├─bluechi-agent.service
│ │ └─396 /usr/libexec/bluechi-agent
│ ├─dbus-broker.service
│ │ ├─399 /usr/bin/dbus-broker-launch --scope system
--audit
│ │ └─401 dbus-broker --log 4 --controller 9 --machin
e-id a83253ae278d7394cb38e975535590d7 --max-bytes 536870912 --max-fds 4096 --max
-matches 16384 --audit
```
### List QM container via podman
```console
# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a83253ae278d /sbin/init 38 seconds ago Up 38 seconds qm
```
### Extend QM quadlet managed by podman
QM quadlet file is shipped through rpm, refer the following file.
qm.container which is installed to /usr/share/containers/systemd/qm.container
Please refer `man quadlet` for the supported value and how to.
In case a change needed in quadlet file, do not update systemd/qm.container file
As per `man quadlet` do the following:
```console
if ! test -e /etc/containers/systemd/qm.container.d ; then
mkdir -p /etc/containers/systemd/qm.container.d
fi
cat > "/etc/containers/systemd/qm.container.d/expose-dev.conf" <<EOF
[Container]
# Expose host device /dev/net/tun
AddDevice=-/dev/net/tun
# In case parameter override needed, add empty value before the required key
Unmask=
Unmask=ALL
EOF
```
To verify the result use the following command:
```console
/usr/lib/systemd/system-generators/podman-system-generator --dryrun
```
Once the result is satisfied, apply the following
```console
systemctl daemon-reload
systemctl restart qm
systemctl is-active qm
active
```
### Connecting to QM container via podman
```console
# podman exec -it qm bash
bash-5.1#
```
### SSH guest CentOS Automotive Stream Distro
Make sure the CentOS Automotive Stream Distro Virtual Machine/Container is running with SSHD enabled
and permits ssh connection from root user.
Add **PermitRootLogin yes** into **sshd_config**
```bash
host> vi /etc/ssh/sshd_config
```
Restart systemctl restart sshd
```bash
host> systemctl restart sshd
```
Find the port the ssh is listening in the VM
```bash
host> netstat -na |more # Locate the port (2222 or 2223, etc)
```
Example connecting from the terminal to the Virtual Machine:
```bash
connect-to-VM-via-SSH> ssh root@127.0.0.1 \
-p 2222 \
-oStrictHostKeyChecking=no \
-oUserKnownHostsFile=/dev/null
```
### Check if HOST and Container are using different network namespace
#### HOST
```console
[root@localhost ~]# ls -l /proc/self/ns/net
lrwxrwxrwx. 1 root root 0 May 1 04:33 /proc/self/ns/net -> 'net:[4026531840]'
```
#### QM
```console
bash-5.1# ls -l /proc/self/ns/net
lrwxrwxrwx. 1 root root 0 May 1 04:33 /proc/self/ns/net -> 'net:[4026532287]'
```
### Debugging with podman in QM
```console
bash-5.1# podman --root /usr/share/containers/storage pull alpine
Error: creating runtime static files directory "/usr/share/containers/storage/libpod":
mkdir /usr/share/containers/storage: read-only file system
```
### Creating your own dropin QM subpackage
We recommend using the existing drop-in files as a guide and adapting them to your specific needs. However, here are the step-by-step instructions:
1) Create a drop-in file in the directory: `etc/qm/containers/containers.conf.d`
2) Add it as a sub-package to `rpm/qm.spec`
3) Test it by running: `make clean && VERSION=YOURVERSIONHERE make rpm`
4) Additionally, test it with and without enabling the sub-package using (by default it should be disabled but there are cases where it will be enabled by default if QM community decide):
Example changing the spec and triggering the build via make (feel free to automate via sed, awk etc):
```bash
# Define the feature flag: 1 to enable, 0 to disable
# By default it's disabled: 0
%define enable_qm_dropin_img_tempdir 1
$ make clean && VERSION=YOURVERSIONHERE make rpm
```
### Let automation create publish PR subpackages
subpuckges could be created by Packit and uploaded
by Copr to packit/containers-qm-<PR_ID> repo.
Default macros for each subpackage deactivated by default.
To enable PR repo apply the follwoing
1. Enable subpackage spec macro definition in .packit.sh
Add the following line at the end of file,
```bash
# Update build additional rpms in spec
sed -i 's/\(<spec_file_macro_name> \).*/\11/' ${SPEC_FILE}
```
Check rpms created in PT Actions under PR Checks > Packit-as-a-Service
In case new tests need the sub-package, it will be innstalled immediatly
on Packit-as-a-Service test phase.
### Install PR copr sub-packages on local machine
1. Enbale repo in your machine
This part is done automatically by TestingFarm guest provisioning.
In case of manual installation,
```bash
dnf copr enable packit/containers-qm-<PR_ID> <distro><arch>
```
1. Install rpm in qm
This part is done automatically by TestingFarm guest provisioning.
In case of manual installation,
```bash
podman cp /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:packit:containers-qm-<PR_ID>.repo qm:/etc/yum.repos.d/
dnf install --releasever=<VERSION_ID> --installroot /usr/lib/qm/rootfs/ <package>
```
### Debugging with quadlet
Imagine a situation where you have a Quadlet container inside QM that isn't starting, and you're unsure why. The best approach is to log into the QM, run the ```quadlet --dryrun``` command, and analyze what's happening. Here's how you can troubleshoot the issue step by step.
```bash
$ sudo podman exec -it qm bash
bash-5.1# cd /etc/containers/systemd/
bash-5.1# ls
ros2-rolling.container
bash-5.1# /usr/libexec/podman/quadlet --dryrun
quadlet-generator[1068]: Loading source unit file /etc/containers/systemd/ros2-rolling.container
quadlet-generator[1068]: converting "ros2-rolling.container": unsupported key 'Command' in group 'Container' in /etc/containers/systemd/ros2-rolling.container
bash-5.1#
```
As you can see above, the error occurs because the Quadlet is attempting to use an unsupported key from the Service section in the Container group. Removing the unsupported key ```Command``` from ```ros2-rolling.container``` and then reloading or restarting the service should resolve the issue.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 KiB

View File

@ -1,419 +0,0 @@
# Subpackages
Subpackages are **experimental approach** to deliver in a single point (RPM) dropin files
and additional requirements.
The qm project is designed to provide a flexible and modular environment for managing
Quality Management (QM) software in containerized environments. One of the key features
of the qm package is its support for sub-package(s), such as the qm-dropin sub-packages.
These sub-packages are not enabled by default and are optional. However, allow users
to easily extend or customize their QM environment by adding specific configurations,
tools, or scripts to the containerized QM ecosystem by simple installing or uninstalling
a RPM package into the system.
The key features of QM Sub-Packages are
- **Modularity**
- No configuration change, no typo or distribution rebuild/update.
- Just dnf install/remove from the traditional rpm schema.
- **Customizability**
- Users can easily add specific configurations to enhance or modify the behavior of their QM containers.
- **Maintainability**
- Sub-packages ensure that the base qm package remains untouched, allowing easy updates without breaking custom configurations.
- **Simplicity**
- Like qm-dropin provide a clear directory structure and templates to guide users in customizing their QM environment.
!!! note
The following sections describe the currently available QM subpackages.
## Building QM sub-packages
Choose one of the following sub-packages and build using make.
```bash
git clone git@github.com:containers/qm.git && cd qm
Example of subpackages: input, kvm, sound, tty7, ttyUSB0, video, windowmanager
make TARGETS=input subpackages
ls rpmbuild/RPMS/noarch/
qm-0.6.7-1.fc40.noarch.rpm qm_mount_bind_input-0.6.7-1.fc40.noarch.rpm
```
## Installing QM sub-packages
```bash
$ sudo dnf install ./rpmbuild/RPMS/noarch/qm_mount_bind_input-0.6.7-1.fc40.noarch.rpm
<SNIP>
Complete!
```
If QM is already running, restart or reload your QM container environment to apply the new configurations.
```bash
sudo systemctl daemon-reload
sudo podman restart qm
```
## Removing QM sub-packages
```bash
sudo rpm -e qm_mount_bind_input
```
## Creating your own drop-in QM sub-package
We recommend using the existing drop-in files as a guide and adapting them to your specific needs. However, here are the step-by-step instructions:
1) Add a drop-in file to: `etc/containers/systemd/qm.container.d/qm_dropin_<subpackage>.conf>`
2) Add your package as a sub-package to: `rpm/<subpackage_directory>/<subpackage>.spec`
3) Add the makefile for the sub-package and any files required by the sub-package to: `subsystems/<subpackage_directory>`
4) Test the sub-package build by running: `make clean && make TARGETS=<subpackage> subpackages`
5) Install your sub-package using: `dnf install -y rpmbuild/RPMS/noarch/<subpackage>*.noarch.rpm`
6) Restart podman container using: `sudo podman restart qm`
7) Additionally, test it with and without enabling the sub-package using (by default it should be disabled but there are cases where it will be enabled by default if QM community decide):
Example changing the spec and triggering the build via make (feel free to automate via sed, awk etc):
```bash
# Use make file to run specific subpackage
make TARGETS=windowmanager subpackages
```
## QM sub-package Input
The `input` sub-package exposes `/dev/input/*` devices (such as keyboards, mice, touchpads, etc.) from the host system to the QM container.
Follow the steps below to verify that the input sub-package properly mounts and exposes input devices inside the QM container.
### Step 1: Verify input devices are NOT visible inside QM
```bash
host> sudo podman exec -it qm ls /dev/input
ls: cannot access '/dev/input': No such file or directory
```
### Step 2: Build and install the input sub-package
```bash
host> make TARGETS=input subpackages
host> sudo dnf install ./rpmbuild/RPMS/noarch/qm_mount_bind_input-0.7.4-1.fc41.noarch.rpm
```
### Step 3: Confirm input devices exist on the host
```bash
host> ls /dev/input
by-id event0 event2 event4 js0 mouse0 mouse2
by-path event1 event3 event5 mice mouse1
```
### Step 4: Restart QM to apply the mount bind configuration
```bash
host> sudo systemctl daemon-reload
host> sudo podman restart qm
```
### Step 5: Re-check input devices inside QM
```bash
host> sudo podman exec -it qm ls /dev/input
event0 event2 event4 js0 mouse0 mouse2
event1 event3 event5 mice mouse1
```
## QM sub-package tty7
The tty7 sub-package exposes `/dev/tty7` to the container. `/dev/tty7` is typically the virtual terminal associated with the graphical user interface (GUI) on Linux systems.
Follow the steps below to verify that the input sub-package properly mounts and exposes input devices inside the QM container.
### Step 1: Verify tty7 is NOT visible inside QM
```bash
host> sudo podman exec -it qm ls -l /dev/tty7
ls: cannot access '/dev/tty7': No such file or directory
```
### Step 2: Build and install the tty7 sub-package
```bash
host> make TARGETS=tty7 subpackages
host> sudo dnf install ./rpmbuild/RPMS/noarch/qm-mount-bind-tty7-0.7.4-1.fc41.noarch.rpm
```
### Step 3: Restart QM to apply the mount bind configuration
```bash
host> sudo systemctl daemon-reload
host> sudo podman restart qm
```
### Step 4: Re-check tty7 inside QM
```bash
host> sudo podman exec -it qm ls -l /dev/tty7
crw--w----. 1 root tty 4, 7 Apr 15 13:34 /dev/tty7
```
## QM sub-package ttyUSB0
The ttyUSB0 sub-package exposes /dev/ttyUSB0 to the QM container. This device node is commonly used for USB-to-serial adapters, which are widely used to connect embedded systems, IoT devices, or other serial-based equipment.
### Step 1: Verify ttyUSB0 is NOT visible inside QM
```bash
host> sudo podman exec -it qm ls -l /dev/ttyUSB0
ls: cannot access '/dev/ttyUSB0': No such file or directory
```
### Step 2: Build and install the ttyUSB0 sub-package
```bash
host> make TARGETS=ttyUSB0 subpackages
host> sudo dnf install ./rpmbuild/RPMS/noarch/qm-mount-bind-ttyUSB0-0.7.4-1.fc41.noarch.rpm
```
### Step 3: Restart QM to apply the configuration
```bash
host> sudo systemctl daemon-reload
host> sudo podman restart qm
```
### Step 4: Re-check ttyUSB0 inside QM
```bash
host> sudo podman exec -it qm ls -l /dev/ttyUSB0
crw-rw-rw-. 1 root root 4, 64 Apr 24 08:50 /dev/ttyUSB0
```
### Additional Notes
- Make sure the USB-to-serial device is connected to the host machine before restarting QM.
- You can fake ttyUSB0 connection on host machine for testing reasons with:
```bash
sudo mknod /dev/ttyUSB0 c 4 64
sudo chmod 666 /dev/ttyUSB0
```
## QM sub-package Video
The video sub-package exposes `/dev/video0` (or many video devices required) to the container. This feature is useful for demonstrating how to share a camera from the host system into a container using Podman drop-in. To showcase this functionality, we provide the following demo:
### Building the video sub-package, installing, and restarting QM
```bash
make TARGETS=video subpackages
sudo dnf install ./rpmbuild/RPMS/noarch/qm-mount-bind-video-0.6.7-1.fc40.noarch.rpm
sudo systemctl daemon-reload
sudo podman restart qm
```
This simulates a rear camera when the user shifts into reverse gear.
In this simulation, we created a systemd service that, every time it is started, captures a snapshot from the webcam, simulating the action of a rear camera. (Feel free to start and restart the service multiple times!)
```bash
host> sudo podman exec -it qm bash
bash-5.2# systemctl daemon-reload
bash-5.2# systemctl start rear-camera
# ls -la /var/tmp/screenshot.jpg
-rw-r--r--. 1 root root 516687 Oct 13 04:05 /var/tmp/screenshot.jpg
bash-5.2#
```
### Copy the screenshot to the host and view it
```bash
host> sudo podman cp qm:/var/tmp/screenshot.jpg .
```
Great job! Now imagine all the possibilities this opens up!
## QM sub-package Sound
### Step 1: Install the QM Mount Bind Sound Package
To set up sound cards in a QM environment using Podman, follow the steps below:
Run the following commands to install the `qm_mount_bind_sound` package and restart QM (if previously in use):
```bash
# Build and install the RPM for QM sound
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=sound subpackages
sudo dnf install -y rpmbuild/RPMS/noarch/qm_mount_bind_sound-0.6.7-1.fc40.noarch.rpm
# Restart QM container (if already running)
sudo systemctl daemon-reload
sudo podman restart qm
```
### Step 2: Identify Sound Cards
After installing the drop-in and restarting QM, you need to identify which sound card in the Linux system will be used in QM. If you're familiar with your sound card setup feel free to skip this step.
To list the sound cards available on your system (in our case, we will pick the number 1):
```bash
cat /proc/asound/cards
```
**Example Output**:
```bash
0 [NVidia ]: HDA-Intel - HDA NVidia
HDA NVidia at 0x9e000000 irq 17
1 [sofhdadsp ]: sof-hda-dsp - sof-hda-dsp
LENOVO-20Y5000QUS-ThinkPadX1ExtremeGen4i
2 [USB ]: USB-Audio - USB Audio Device
Generic USB Audio at usb-0000:00:14.0-5, full speed
```
### Detecting Channels and Sample Rates
To list the supported number of channels and samples use `pactl` command:
```bash
pactl list sinks | grep -i 48000 | uniq
Sample Specification: s24-32le 2ch 48000Hz
```
### Verify Sample Rate Support
To show the supported sample rates for a specific sound card codec, you can also inspect the codec details:
```bash
cat /proc/asound/card1/codec#0 | grep -i rates
```
This will output the supported sample rates for the codec associated with `card1`.
### Differentiating Between Cards
Accessing Card 1 (sof-hda-dsp)
```bash
cat /proc/asound/cards | grep -A 1 '^ 1 '
```
Accessing Card 2 (USB Audio Device)
```bash
cat /proc/asound/cards | grep -A 1 '^ 2 '
```
### Step 3: Testing audio inside QM
Inside QM, run the following command:
```bash
podman exec -it qm bash
bash-# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76dacaa9a89e quay.io/qm-images/audio:latest sleep infinity 7 hours ago Up 7 hours systemd-audio
bash-# podman exec -it systemd-audio bash
Execute the audio test within the nested container, and the sound will be output through the physical speakers of your computer—or, in this case, the car's multimedia soundbox.
bash-# speaker-test -D hw:1,0 -c 2 -r 48000
```
Params:
```bash
hw:1,0: sound card 1, device 0
-c 2: two channels (stereo)
-r 48000: sample rate of 48 kHz
```
## QM sub-package ROS2
The QM sub-package ROS2 (a.k.a "The Robot Operating System" or middleware for robots) is widely used by open-source projects, enterprises, companies, edge env and government agencies, including NASA, to advance robotics and autonomous systems. Enabled by Quadlet in QM, ROS2 on top of QM provides a secure environment where robots can operate and communicate safely, benefiting from QM's "Freedom from Interference" frequently tested layer. This ensures robots can function without external interference, enhancing their reliability and security.
The types of robots compatible with this environment are extensive, ranging from medical devices and aerial drones to aqua drones and space rockets. ROS2 within QM supports high availability, meaning these robotic systems can maintain continuous operations, crucial for mission-critical and industrial applications. This versatility makes it ideal for environments that demand robust communication and operational safety, from healthcare and aerospace to underwater exploration and autonomous land vehicles.
How to test this env?
```bash
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=ros2_rolling subpackages
sudo dnf install rpmbuild/RPMS/noarch/qm_ros2_rolling-0.6.7-1.fc40.noarch.rpm -y
sudo systemctl daemon-reload
sudo podman restart qm # if you have qm already running
Testing using talker and listener examples
$host> sudo podman exec -it qm bash
QM> . /opt/ros/jazzy/setup.bash # always replace jazz with the image ROS distro
QM> ros2 run demo_nodes_cpp talker &
QM> ros2 run demo_nodes_cpp listener
```
## QM sub-package KVM
The QM sub-package KVM includes drop-in configuration that enables the integration of Kernel-based Virtual Machine (KVM) management into the QM (Quality Management) container environment.
This configuration allows users to pull containerized kvm from [qm-images-repo](https://quay.io/repository/qm-images/kvm) and run it inside QM
There is also kvm.container which is installed as a service.
Below example step by step:
Step 1: clone QM repo, create rpm.
```bash
git clone https://github.com/containers/qm.git && cd qm
make TARGETS=kvm subpackages
```
Step 2: copy rpm to running machine
```bash
scp -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -P 2222 rpmbuild/RPMS/noarch/qm-kvm-0.7.4-1.fc41.noarch.rpm root@127.0.0.1:/root/
```
Step 3: ssh machine install and verify
```bash
sudo dnf install ./qm-kvm-0.7.4-1.fc41.noarch.rpm
sudo systemctl restart qm # if you have qm already running
```
Step 4: verify, configuration exist
```bash
ls -ltr /etc/containers/systemd/qm.container.d/
total 12
-rw-r--r--. 1 root root 34 Jan 1 1970 publish-port.conf
-rw-r--r--. 1 root root 139 Jul 21 2023 qm_dropin_mount_bind_kvm.conf
ls -ltr /etc/qm/containers/systemd/
total 12
-rw-r--r--. 1 root root 91 Jan 1 1970 nginx.container
-rw-r--r--. 1 root root 188 Jul 21 2023 kvm.container
[root@localhost ~]# podman exec qm systemctl is-active kvm
active
[root@localhost ~]# podman exec -it qm sh
sh-5.1# ssh fedora@localhost -p 2226
[fedora@ibm-p8-kvm-03-guest-02 ~]$ grep ^NAME /etc/os-release
NAME="Fedora Linux"
```
### AutoSD install
Some notes related to installing qm on ostree AutoSD image
1. Check /var/qm size is larger then 1.5G
2. Installing in ostree images with dnf command, requires running rpm-ostree usroverlay
In case using aib schema to build your image, verify adding the following to build command
```bash
--define 'extra_rpms=["audit","dnf","python3-gobject"] qm_varpart_relative_size=0.5'
```

View File

@ -1,17 +0,0 @@
## Installing QM
The first step to getting started with QM is installation.
Fedora or CentOS:
On Fedora and CentOS-Stream systems (with EPEL repository enabled), QM can be directly installed via:
```bash
dnf install qm
```
## RPM Mirrors
Looking for a specific version of QM?
Search in the mirrors list below.
[CentOS Automotive SIG - qm package - noarch](https://mirror.stream.centos.org/SIGs/9-stream/automotive/aarch64/packages-main/Packages/q/)

View File

@ -1,11 +0,0 @@
# QM
## QM is a containerized environment for running Functional Safety QM (Quality Management) software
The qm package sets up an isolated runtime environment for non-critical processes, managed through container tools and systemd. It is designed to ensure that these processes do not interfere with the host system, making it ideal for scenarios such as ASIL (Automotive Safety Integrity Level) separation.
QM runs as an exploded container—a persistent, containerized root filesystem mounted under /var/lib/qm/rootfs. It operates with its own instance of systemd, effectively creating a nested user space within its dedicated disk partition. This setup allows the system to isolate and control resource usage via cgroups, namespaces, and security constraints.
System-level tooling like Podman and systemd inside QM are fully independent from the host, so even container commands themselves are sandboxed. The environment is provisioned using Podman and configured with quadlet units, which streamline setup and lifecycle management.
Software installed inside the QM root is automatically isolated from the host. Developers can further segment workloads by using container tools inside QM to manage additional levels of containment for processes requiring extra isolation.

View File

@ -1,72 +0,0 @@
# Setting up IPC
In systems where **Automotive Safety Integrity Level (ASIL)** and **Quality Management (QM)**
components coexist, strict separation is enforced to maintain safety and security boundaries via
**SELinux (Security-Enhanced Linux)**, which labels processes and files with security contexts
to control their interactions.
**IPC (Inter-Process Communication)** between ASIL and QM components must be tightly controlled.
To comply with SELinux policies and avoid permission denials, any socket-based communication
between ASIL and QM domains should be established in the dedicated directory such as /run/ipc
with ipc_var_run_t file context. It serves as a secure bridge for cross-domain communication
while maintaining SELinux isolation.
On the other hand, **IPC between QM services** (e.g., two services or containers within the same QM domain)
can occur as well. Since these components share the same SELinux type and context, they are allowed to
communicate using standard Unix domain sockets located in /run. This approach simplifies internal QM
communication without compromising the system's overall security posture. Such communication can be
orchestrated also using container orchestration patterns like **.pod (Podman pod definitions)** or
**.kube (Kubernetes pod manifests)**, which group related services in shared namespaces to support efficient
IPC within the same trust boundary.
## Example QM to QM app
## /etc/qm/containers/systemd/ipc_client.container
```console
[Unit]
Description=Demo client service container
Requires=ipc_server.socket
After=ipc_server.socket
[Container]
Image=quay.io/username/ipc-demo/ipc_client:latest
Network=none
Volume=/run/:/run/
SecurityLabelLevel=s0:c1,c2
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
```
## /etc/qm/containers/systemd/ipc_server.container
```console
[Unit]
Description=Demo server service container
Requires=ipc_server.socket
After=ipc_server.socket
[Container]
Image=quay.io/username/ipc-demo/ipc_server:latest
Network=none
Volume=/run/:/run/
SecurityLabelLevel=s0:c1,c2
[Service]
Restart=always
Type=notify
[Install]
WantedBy=multi-user.target
```
## /etc/qm/systemd/system/ipc_server.socket
```console
[Unit]
Description=IPC Server Socket
[Socket]
ListenStream=%t/ipc_server.socket
SELinuxContextFromNet=yes
[Install]
WantedBy=sockets.target
```

View File

@ -1,6 +0,0 @@
# Additional Resources
- [Paving the Way for Uninterrupted Car Operations - DevConf Boston 2024](https://www.youtube.com/watch?v=jTrLqpw7E6Q)
- [Security - Sample Risk Analysis according to ISO26262](https://www.youtube.com/watch?v=jTrLqpw7E6Q&t=1268s)
- [ASIL and QM - Simulation and Service Monitoring using bluechi and podman](https://www.youtube.com/watch?v=jTrLqpw7E6Q&t=1680s)
- [Containers in a Car - DevConf.CZ 2023](https://www.youtube.com/watch?v=FPxka5uDA_4)

View File

@ -1,262 +0,0 @@
# Using QM
This section describes how to interact with QM.
## Installing software inside QM partition
```bash
dnf --installroot /usr/lib/qm/rootfs/ install vim -y
```
## Removing software inside QM partition
```bash
dnf --installroot /usr/lib/qm/rootfs/ remove vim -y
```
## Copying files to QM partition
Please note: This process is only applicable for regular images.
OSTree images are read-only, and any files must be included during the build process.
Once this is understood, proceed by executing the following command on the host after
the QM package has been installed.
```bash
#host> cp file_to_be_copied /usr/lib/qm/rootfs/root
#host> podman exec -it qm bash
bash-5.1> ls /root
file_to_be_copied
```
## Listing QM service
```bash
[root@localhost ~]# systemctl status qm -l
● qm.service
Loaded: loaded (/usr/share/containers/systemd/qm.container; generated)
Active: active (running) since Sun 2024-04-28 22:12:28 UTC; 12s
ago
Main PID: 354 (conmon)
Tasks: 7 (limit: 7772)
Memory: 82.1M (swap max: 0B)
CPU: 945ms
CGroup: /qm.service
├─libpod-payload-a83253ae278d7394cb38e975535590d71de90a41157b547040
4abd6311fd8cca
│ ├─init.scope
│ │ └─356 /sbin/init
│ └─system.slice
│ ├─bluechi-agent.service
│ │ └─396 /usr/libexec/bluechi-agent
│ ├─dbus-broker.service
│ │ ├─399 /usr/bin/dbus-broker-launch --scope system
--audit
│ │ └─401 dbus-broker --log 4 --controller 9 --machin
e-id a83253ae278d7394cb38e975535590d7 --max-bytes 536870912 --max-fds 4096 --max
-matches 16384 --audit
```
## List QM container via podman
```console
# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a83253ae278d /sbin/init 38 seconds ago Up 38 seconds qm
```
## Extend QM quadlet managed by podman
QM quadlet file is shipped through rpm, refer the following file.
qm.container which is installed to /usr/share/containers/systemd/qm.container
Please refer `man quadlet` for the supported value and how to.
In case a change needed in quadlet file, do not update systemd/qm.container file
As per `man quadlet` do the following:
```console
if ! test -e /etc/containers/systemd/qm.container.d ; then
mkdir -p /etc/containers/systemd/qm.container.d
fi
cat > "/etc/containers/systemd/qm.container.d/expose-dev.conf" <<EOF
[Container]
# Expose host device /dev/net/tun
AddDevice=-/dev/net/tun
# In case parameter override needed, add empty value before the required key
Unmask=
Unmask=ALL
EOF
```
To verify the result use the following command:
```console
/usr/lib/systemd/system-generators/podman-system-generator --dryrun
```
Once the result is satisfied, apply the following
```console
systemctl daemon-reload
systemctl restart qm
systemctl is-active qm
active
```
## Managing CPU usage
Using the steps below, it's possible to manage CPU usage of the `qm.service` by modifying service attributes and utilizing drop-in files.
### Setting the CPUWeight attribute
Modifying the `CPUWeight` attribute affects the priority of the `qm.service`. A higher value prioritizes the service, while a lower value deprioritizes it.
Inspect the current CPUWeight value:
```bash
systemctl show -p CPUWeight qm.service
```
Set the CPUWeight value:
```bash
systemctl set-property qm.service CPUWeight=500
```
### Limiting CPUQuota
It's also possible to limit the percentage of the CPU allocated to the `qm.service` by defining `CPUQuota`. The percentage specifies how much CPU time the unit shall get at maximum, relative to the total CPU time available on one CPU.
Inspect the current `CPUQuota` value via the `CPUQuotaPerSecUSec` property:
```bash
systemctl show -p CPUQuotaPerSecUSec qm.service
```
Set the `CPUQuota` value of `qm.service` on the host using:
```bash
systemctl set-property qm.service CPUQuota=50%
```
Verify the `CPUQuota` drop in file has been created using the command below.
```bash
systemctl show qm.service | grep "DropInPath"
```
Expected output:
```bash
DropInPaths=/usr/lib/systemd/system/service.d/10-timeout-abort.conf /etc/systemd/system.control/qm.service.d/50-CPUQuota.conf
```
To test maxing out CPU usage and then inspect using the `top` command, follow these steps:
- Set the `CPUQuota` value of `qm.service` on the host using:
```bash
systemctl set-property qm.service CPUQuota=50%
```
- Execute this command to stress the CPU for 30 seconds:
```bash
podman exec qm timeout 30 dd if=/dev/zero of=/dev/null
```
- Observe the limited CPU consumption from the `qm.service`, as shown in the output of the command below:
```bash
top | head
```
Expected output:
```bash
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1213867 root 20 0 2600 1528 1528 R 50.0 0.0 4:15.21 dd
3471 user 20 0 455124 7568 6492 S 8.3 0.0 1:43.64 ibus-en+
1 root 20 0 65576 37904 11116 S 0.0 0.1 0:40.00 systemd
```
## Connecting to QM container via podman
```console
# podman exec -it qm bash
bash-5.1#
```
## SSH guest CentOS Automotive Stream Distro
Make sure the CentOS Automotive Stream Distro Virtual Machine/Container is running with SSHD enabled
and permits ssh connection from root user.
Add **PermitRootLogin yes** into **sshd_config**
```bash
host> vi /etc/ssh/sshd_config
```
Restart systemctl restart sshd
```bash
host> systemctl restart sshd
```
Find the port the ssh is listening in the VM
```bash
host> netstat -na |more # Locate the port (2222 or 2223, etc)
```
Example connecting from the terminal to the Virtual Machine:
```bash
connect-to-VM-via-SSH> ssh root@127.0.0.1 \
-p 2222 \
-oStrictHostKeyChecking=no \
-oUserKnownHostsFile=/dev/null
```
## Check if HOST and Container are using different network namespace
### HOST
```console
[root@localhost ~]# ls -l /proc/self/ns/net
lrwxrwxrwx. 1 root root 0 May 1 04:33 /proc/self/ns/net -> 'net:[4026531840]'
```
### QM
```console
bash-5.1# ls -l /proc/self/ns/net
lrwxrwxrwx. 1 root root 0 May 1 04:33 /proc/self/ns/net -> 'net:[4026532287]'
```
## Debugging with podman in QM
```console
bash-5.1# podman --root /usr/share/containers/storage pull alpine
Error: creating runtime static files directory "/usr/share/containers/storage/libpod":
mkdir /usr/share/containers/storage: read-only file system
```
## Debugging with quadlet
Imagine a situation where you have a Quadlet container inside QM that isn't starting, and you're unsure why. The best approach is to log into the QM, run the ```quadlet --dryrun``` command, and analyze what's happening. Here's how you can troubleshoot the issue step by step.
```bash
$ sudo podman exec -it qm bash
bash-5.1# cd /etc/containers/systemd/
bash-5.1# ls
ros2.container
bash-5.1# /usr/libexec/podman/quadlet --dryrun
quadlet-generator[1068]: Loading source unit file /etc/containers/systemd/ros2.container
quadlet-generator[1068]: converting "ros2.container": unsupported key 'Command' in group 'Container' in /etc/containers/systemd/ros2.container
bash-5.1#
```
As you can see above, the error occurs because the Quadlet is attempting to use an unsupported key from the Service section in the Container group. Removing the unsupported key ```Command``` from ```ros2.container``` and then reloading or restarting the service should resolve the issue.

View File

@ -1,38 +0,0 @@
site_name: QM Documentation
repo_url: https://github.com/containers/qm
repo_name: qm
edit_uri: blob/main/docs/docs/
copyright: Copyright Contributors to the QM project
nav:
- Home: index.md
- Getting Started: getting_started.md
- Using QM: usage.md
- Setting up IPC: ipc.md
- How To:
- Android container: how_tos/android.md
- Using network modes with QM: how_tos/network.md
- Changing variables in QM: how_tos/qm_variables.md
- Experimental:
- QM Subpackages: experimental/subpackages.md
- Additional resources: resources.md
theme:
name: material
features:
- content.code.copy
- navigation.indexes
markdown_extensions:
- toc:
permalink: True
- sane_lists
- smarty
- admonition
- pymdownx.snippets:
base_path: ["docs"]
check_paths: True
- pymdownx.superfences:
- pymdownx.tabbed:
alternate_style: true

View File

@ -1,7 +1,11 @@
# Changing variables in qm containers.conf
# Title: How to change the variables in qm containers.conf
## Description
The `container.conf` file needs to be modified to allow pulling images larger than 1G from the repository on OStree images.
Input:
## Update container image_copy_tmp_dir if the image is an OStree
1. Create /var/qm/tmp.dir or differently named directory on host.

View File

@ -1,6 +1,4 @@
# Virtualization: Android container with Quadlet
This is an example of an Android container running on top of kvm using quadlet and Wayland:
# An example of Android container running on top of kvm using quadlet and Wayland
```console
$ cat ~/.config/containers/systemd/android.container

View File

@ -1,3 +0,0 @@
mkdocs>=1.3.0
mkdocs-material>=9.3.1
pymdown-extensions>=10.0.1

View File

@ -1,22 +1,20 @@
# Using network modes with QM
## Basics: Network Modes in Podman
# Network Modes in Podman
When running a container with Podman, you can specify the network mode using the `--network` flag. Two common options are `host` and `private`.
### Network=host
## Network=host
If you set `--network=host`, the container will use the host's network stack. This means the container will share the same network namespace as the host, and will be able to access the host's network interfaces, IP addresses, and ports.
In this mode, the container is not isolated from the host's network, and can potentially access sensitive network resources. This can be useful for certain use cases, such as running a container that needs to access a specific network interface or port on the host.
### Network=private (default)
## Network=private (default)
By default, Podman uses the `private` network mode. This means that the container will have its own isolated network namespace, and will not be able to access the host's network interfaces, IP addresses, or ports.
In this mode, the container is isolated from the host's network, and can only communicate with other containers on the same network. This provides a higher level of security, as the container is not able to access sensitive network resources on the host.
### Security Implications
## Security Implications
The reason `private` is the default network mode is due to security concerns. By isolating the container's network namespace, Podman prevents the container from accessing sensitive network resources on the host, such as:
@ -29,7 +27,7 @@ This helps to prevent potential security vulnerabilities, such as:
* Container escape: a container accessing sensitive resources on the host
* Lateral movement: a container accessing other containers on the host
### Example
## Example
To illustrate the difference, consider the following example:
@ -38,47 +36,9 @@ To illustrate the difference, consider the following example:
podman run -it --network=host fedora /bin/bash
# Run a container with network=private (default)
podman run -it --network=private fedora /bin/bash
podman run -it fedora /bin/bash
```
In the first example, the container will share the host's network namespace, while in the second example, the container will have its own isolated network namespace.
For more information, see the [Podman Networking Tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/basic_networking.md).
For network modes configuration example using quadlets, see [Quadlet Network Example](https://github.com/containers/qm/blob/main/docs/quadlet-examples/network/README.md).
## Quadlet example running host and private networks
Here is an example of running a network-test container using quadlets for both --network=host and --network=private. You should place this file either in /usr/share/containers/systemd/ or /etc/containers/systemd/
```console
/usr/share/containers/systemd/
/etc/containers/systemd/
```
For rootless users:
```console
$HOME/.config/containers/systemd/
```
Host Network
```console
# network-test.container
[Container]
ContainerName=network-test
Image=localhost/local-audio-image
Network=host
```
Private Network
```console
# network-test.container
[Container]
ContainerName=network-test
Image=localhost/local-audio-image
Network=private
```

View File

@ -9,3 +9,4 @@ Mount=type=bind,source=/dev/tty4,target=/dev/tty4
Mount=type=bind,source=/dev/tty5,target=/dev/tty5
Mount=type=bind,source=/dev/tty6,target=/dev/tty6
Mount=type=bind,source=/dev/tty7,target=/dev/tty7
Mount=type=bind,source=/dev/tty0,target=/dev/tty0

View File

@ -24,10 +24,6 @@ adjust:
script: |
cd tests/e2e
./set-ffi-env-e2e "${FFI_SETUP_OPTIONS}"
- name: Place quadlet for ffi-qm container
how: shell
script: |
cp tests/ffi/common/ffi-qm.container /etc/qm/containers/systemd/
execute:
how: tmt

View File

@ -2,7 +2,7 @@ summary: Kvm Tier 0 - QM sanity test
discover:
how: fmf
filter: 'tier:0&tag:kvm|tier:0&tag:qmctl-test'
filter: 'tier:0&tag:kvm'
prepare+:
- name: Enable copr and install rpms

12
qm.8.md
View File

@ -40,7 +40,7 @@ systemctl status qm.service
Tasks: 11 (limit: 76801)
Memory: 275.1M (swap max: 0B)
CPU: 4.527s
CGroup: /qm.service
CGroup: /QM.slice/qm.service
├─libpod-payload-00de006493bc970788d6c830beb494a58a9a2847a5eda200812d3a8b4e214814
│ ├─init.scope
│ │ └─993676 /sbin/init
@ -53,13 +53,11 @@ systemctl status qm.service
...
```
## CGroups and container configuration
## CGROUPS QM.slice
The options in the qm.container file overridden by using drop-in files, in the
directories `/etc/containers/systemd/qm.container.d` or`
`/usr/lib/containers/systemd/qm.container.d. This allows overriding for example
CGroup options like Service.CPUWeight, or podman options like Container.Volume.
Such options will affect all the processes running in the qm container.
Notice that the QM environment is running systemd and other services within the
QM.Slice. This slice can be used to modify the cgroups controls of all of the
processes within the QM environment.
## Install Additional packages in QM

View File

@ -11,7 +11,7 @@ WantedBy=default.target
# ManagedOOMSwap=auto|kill: Specifies how systemd-oomd.service will act on qm.
# QM cgroup, pass directly to systemd and handled by it,
# please refer to `man systemd.resource-control` for details.
CPUWeight=idle
CPUWeight=50
Delegate=true
IOWeight=50
ManagedOOMSwap=kill
@ -34,10 +34,7 @@ MemorySwapMax=0
# Containers within the qm contain default set OOMScoreAdj to 750
OOMScoreAdjust=500
Restart=always
# qm.service is a toplevel cgroup, so CPUWeight is relative to all other cgroups in that
# parent (such as user.slice and system.slice), otherwise the CPUWeight of qm.service
# is only compared to the other children of its parent.
Slice=-.slice
Slice=QM.slice
Environment=ROOTFS=/usr/lib/qm/rootfs
Environment=RWETCFS=/etc/qm
Environment=RWVARFS=/var/qm
@ -53,6 +50,12 @@ TasksMax=50%
# For details see: https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#addcapability
AddCapability=all
# Unmask
# -------
# Specify the paths to unmask separated by a colon. unmask=ALL or /path/1:/path/2, or shell expanded paths (/proc/*):
# If set to ALL, Podman will unmask all the paths that are masked or made read-only by default.
# For details see: https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#unmask
Unmask=ALL
SecurityLabelNested=true
SeccompProfile=/usr/share/qm/seccomp-no-rt.json
@ -64,7 +67,7 @@ SeccompProfile=/usr/share/qm/seccomp-no-rt.json
PidsLimit=-1
# Comment DropCapability this will allow FFI Tools to surpass their defaults.
DropCapability=sys_boot sys_resource
DropCapability=sys_resource
AddDevice=-/dev/kvm
AddDevice=-/dev/fuse

6
qm.fc
View File

@ -10,8 +10,4 @@
/etc/qm(/.*)? gen_context(system_u:object_r:qm_file_t,s0)
# File context for ipc programs
/usr/lib/qm/rootfs/run/ipc(/.*)? gen_context(system_u:object_r:ipc_var_run_t,s0)
/run/ipc(/.*)? gen_context(system_u:object_r:ipc_var_run_t,s0)
# File context for bluechi-agent inside QM
/usr/lib/qm/rootfs/usr/libexec/bluechi-agent -- gen_context(system_u:object_r:qm_bluechi_agent_exec_t,s0)
/var/run/ipc(/.*)? gen_context(system_u:object_r:ipc_var_run_t,s0)

5
qm.if
View File

@ -15,7 +15,6 @@ template(`qm_domain_template',`
gen_require(`
class dbus { send_msg acquire_svc };
class passwd rootok;
class process setcurrent;
attribute container_domain;
attribute filesystem_type;
@ -61,7 +60,6 @@ template(`qm_domain_template',`
container_exec_share_files($1_t)
allow $1_t container_ro_file_t:file execmod;
allow $1_container_domain $1_file_type:chr_file { rw_inherited_file_perms };
allow $1_t self:process setcurrent;
attribute $1_file_type;
allow $1_file_type self:filesystem associate;
@ -85,7 +83,6 @@ template(`qm_domain_template',`
allow $1_t $1_file_type:chr_file mounton;
allow $1_t $1_file_type:sock_file mounton;
filetrans_pattern(ipc_t, $1_file_t, ipc_var_run_t, dir, "ipc")
list_dirs_pattern($1_t, ipc_var_run_t, ipc_var_run_t)
allow $1_t ipc_var_run_t:dir mounton;
@ -96,7 +93,7 @@ template(`qm_domain_template',`
manage_lnk_files_pattern($1_t, $1_file_type, $1_file_type)
manage_sock_files_pattern($1_t, $1_file_type, $1_file_type)
fs_tmpfs_filetrans($1_t, $1_file_t, { dir file lnk_file })
allow $1_t $1_file_type:chr_file { watch watch_reads map };
allow $1_t $1_file_type:chr_file { watch watch_reads };
allow $1_t $1_file_type:dir { mounton relabelfrom relabelto };
allow $1_t $1_file_type:filesystem all_filesystem_perms;

51
qm.te
View File

@ -1,4 +1,4 @@
policy_module(qm, 0.7.6)
policy_module(qm, 0.7.0)
gen_require(`
attribute container_file_type;
@ -30,56 +30,11 @@ unconfined_domain(ipc_t)
qm_domain_template(qm)
#########################################
#
# bluechi-agent inside QM
#
type qm_bluechi_agent_t;
type qm_bluechi_agent_exec_t;
init_daemon_domain(qm_bluechi_agent_t, qm_bluechi_agent_exec_t)
allow qm_bluechi_agent_t qm_file_t:chr_file read;
allow qm_bluechi_agent_t qm_file_t:dir { open read search getattr };
allow qm_bluechi_agent_t qm_file_t:file { execute getattr open read };
allow qm_bluechi_agent_t qm_file_t:file map;
allow qm_bluechi_agent_t qm_file_t:lnk_file read;
allow qm_bluechi_agent_t qm_file_t:sock_file write;
allow qm_bluechi_agent_t qm_t:unix_dgram_socket sendto;
allow qm_bluechi_agent_t qm_t:unix_stream_socket connectto;
allow qm_bluechi_agent_t self:unix_dgram_socket { create getopt setopt };
allow qm_bluechi_agent_t self:tcp_socket create_stream_socket_perms;
allow qm_bluechi_agent_t qm_t:dbus { send_msg acquire_svc };
allow qm_bluechi_agent_t qm_t:system status;
allow qm_bluechi_agent_t qm_t:system { reload start stop status };
allow qm_bluechi_agent_t qm_file_t:service { reload start stop status };
allow qm_t qm_bluechi_agent_t:dir search;
allow qm_t qm_bluechi_agent_t:file { getattr ioctl open read };
allow qm_t qm_bluechi_agent_t:lnk_file read;
allow qm_t qm_bluechi_agent_t:dbus send_msg;
allow qm_t qm_bluechi_agent_t:process { signull signal sigkill };
unconfined_server_stream_connectto(qm_bluechi_agent_t)
# Allow qm_bluechi_agent_t to connect to any port instead of labelled ones.
gen_tunable(qm_bluechi_agent_port_connect_any, true)
optional_policy(`
require{
type bluechi_var_run_t;
type bluechi_agent_port_t;
type bluechi_t;
}
tunable_policy(`qm_bluechi_agent_port_connect_any',`
corenet_tcp_connect_all_ports(qm_bluechi_agent_t)
',`
allow qm_bluechi_agent_t bluechi_agent_port_t:tcp_socket name_connect;
')
stream_connect_pattern(qm_bluechi_agent_t, bluechi_var_run_t, bluechi_var_run_t, bluechi_t)
stream_connect_pattern(qm_t, bluechi_var_run_t, bluechi_var_run_t, bluechi_t)
unconfined_server_stream_connectto(qm_t)
')

View File

@ -1,5 +1,8 @@
%global debug_package %{nil}
# Define the rootfs macros
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-mount-bind-dvb
Version: 0
Release: 1%{?dist}
@ -9,7 +12,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-dvb-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage installs a drop-in configuration for QM containers to mount bind `/dev/dvb`.
@ -22,7 +25,7 @@ This subpackage installs a drop-in configuration for QM containers to mount bind
install -d %{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d
# Install the dvb drop-in configuration file
install -m 644 %{_builddir}/qm-dvb-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_dvb.conf \
install -m 644 %{_builddir}/qm-video-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_dvb.conf \
%{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_dvb.conf

View File

@ -0,0 +1,30 @@
Name: qm-dropin-img-tempdir
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM nested containers using img tempdir
License: GPL-2.0-only
URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-img_tempdir-%{version}.tar.gz
BuildArch: noarch
Requires: qm = %{version}-%{release}
%description
This sub-package installs drop-in configurations for QM nested containers that use img tempdir.
%prep
%autosetup -Sgit -n qm-img_tempdir-%{version}
%install
install -d %{buildroot}%{_sysconfdir}/qm/containers/containers.conf.d
install -m 644 %{_builddir}/qm-img_tempdir-%{version}/etc/qm/containers/containers.conf.d/qm_dropin_img_tempdir.conf \
%{buildroot}%{_sysconfdir}/qm/containers/containers.conf.d/
%files
%license LICENSE
%doc README.md
%{_sysconfdir}/qm/containers/containers.conf.d/qm_dropin_img_tempdir.conf
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>
- Added img_tempdir mount bind drop-in configuration.

View File

@ -1,6 +1,6 @@
%global debug_package %{nil}
Name: qm-mount-bind-input
Name: qm_mount_bind_input
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM containers to mount bind input devices
@ -9,7 +9,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-input-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This sub-package installs drop-in configurations for QM containers to mount bind input devices.

View File

@ -1,14 +1,10 @@
%global debug_package %{nil}
# rootfs_qm, Define rootfs macro for QM environment not need, do to install command from host
# dnf install --setopt=reposdir=/etc/yum.repos.d <package>
# using qm_sysconfdir /etc/qm/ overlay preventing the detection of quadletfile, need to install
# in the overlay of etc under the host
%define qm_sysconfdir %{_sysconfdir}/qm
# Define rootfs macro for QM environment
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-kvm
# Version: 0
Version: %{version}
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM containers to mount bind /dev/kvm
License: GPL-2.0-only
@ -16,7 +12,17 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-kvm-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
# Build requirements
BuildRequires: make
BuildRequires: podman
BuildRequires: selinux-policy
BuildRequires: selinux-policy-devel
# Runtime dependencies
Requires: qm = %{version}-%{release}
Requires: selinux-policy >= %{_selinux_policy_version}
Requires: selinux-policy-base >= %{_selinux_policy_version}
Requires: podman
%description -n qm-kvm
This subpackage provides a drop-in configuration for the QM environment to enable mount binding of `/dev/kvm` from the host system to containers. This configuration is essential for supporting KVM-based virtualization within QM containers.
@ -24,24 +30,18 @@ This subpackage provides a drop-in configuration for the QM environment to enabl
%prep
%autosetup -Sgit -n qm-kvm-%{version}
%build
%install
# Create the directory for drop-in configurations
install -d %{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d
install -d %{buildroot}%{qm_sysconfdir}/containers/systemd
# Install the KVM drop-in configuration file
install -m 644 %{_builddir}/qm-kvm-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_kvm.conf \
%{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_kvm.conf
install -m 644 %{_builddir}/qm-kvm-%{version}/subsystems/kvm/etc/containers/systemd/kvm.container \
%{buildroot}%{qm_sysconfdir}/containers/systemd/kvm.container
%files -n qm-kvm
%license LICENSE
%doc README.md SECURITY.md
%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_kvm.conf
%{qm_sysconfdir}/containers/systemd/kvm.container
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>

View File

@ -1,9 +1,13 @@
%global debug_package %{nil}
# rootfs macros
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
# Define the feature flag: 1 to enable, 0 to disable
# By default it's disabled: 0
# Some bits borrowed from the openstack-selinux and container-selinux packages
# Some bits borrowed from the openstack-selinux package
%global selinuxtype targeted
%global moduletype services
%global modulenames qm
%global seccomp_json /usr/share/%{modulenames}/seccomp-no-rt.json
@ -16,11 +20,6 @@
# Format must contain '$x' somewhere to do anything useful
%global _format() export %1=""; for x in %{modulenames}; do %1+=%2; %%1+=" "; done;
# RHEL < 10 and Fedora < 40 use file context entries in /var/run
%if %{defined rhel} && 0%{?rhel} < 10 || %{defined fedora} && 0%{?fedora} < 40
%define legacy_var_run 1
%endif
# copr_username is only set on copr environments, not on others like koji
# Check if copr is owned by rhcontainerbot
%if "%{?copr_username}" != "rhcontainerbot"
@ -69,8 +68,7 @@ Requires: parted
Requires: containers-common
Requires: selinux-policy >= %_selinux_policy_version
Requires(post): selinux-policy-base >= %_selinux_policy_version
Requires(post): selinux-policy-any >= %_selinux_policy_version
Recommends: selinux-policy-targeted >= %_selinux_policy_version
Requires(post): selinux-policy-targeted >= %_selinux_policy_version
Requires(post): policycoreutils
Requires(post): libselinux-utils
Requires: podman >= %{podman_epoch}:4.5
@ -95,10 +93,6 @@ use container tools like Podman.
sed -i 's/^install: man all/install:/' Makefile
%build
%if %{defined legacy_var_run}
sed -i 's|^/run/|/var/run/|' qm.fc
%endif
%{__make} all
%install
@ -110,14 +104,13 @@ install -d %{buildroot}%{_sysconfdir}/containers/containers.conf.d
%{__make} DESTDIR=%{buildroot} DATADIR=%{_datadir} install
%post
# Install all modules in a single transaction
%_format MODULES %{_datadir}/selinux/packages/$x.pp.bz2
. %{_sysconfdir}/selinux/config
%selinux_modules_install -s ${SELINUXTYPE} $MODULES
%selinux_modules_install -s %{selinuxtype} $MODULES
# Execute the script to create seccomp rules after the package is installed
/usr/share/qm/create-seccomp-rules
/usr/share/qm/comment-tz-local # FIX-ME GH-issue: 367
# podmand netavark requires at host to load or let's ignore in case host don't have it and proceed with the installation
modprobe ip_tables || true
modprobe ip_tables # podmand netavark requires at host to load
%preun
if [ $1 = 0 ]; then
@ -130,8 +123,7 @@ fi
%postun
if [ $1 -eq 0 ]; then
# This section executes only on package removal, not on upgrade
. %{_sysconfdir}/selinux/config
%selinux_modules_uninstall -s ${SELINUXTYPE} %{modulenames}
%selinux_modules_uninstall -s %{selinuxtype} %{modulenames}
if [ -f %{seccomp_json} ]; then
/bin/rm -f %{seccomp_json}
fi

View File

@ -9,7 +9,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-radio-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage installs a drop-in configuration for QM containers to mount bind `/dev/radio`.

View File

@ -1,9 +1,10 @@
%global debug_package %{nil}
%define qm_sysconfdir %{_sysconfdir}/qm
# rootfs macros for QM ROS2 Rolling
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-ros2
Version: %{version}
Name: qm-ros2-rolling
Version: 0
Release: 1%{?dist}
Summary: Subpackage container for quadlet container to ROS2 Rolling environment
License: GPL-2.0-only
@ -11,7 +12,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-ros2-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage provides a containerized ROS2 Rolling environment within the
@ -26,19 +27,18 @@ containers managed by Podman and systemd within the QM environment.
%install
# Create the necessary directory structure
install -d %{buildroot}%{qm_sysconfdir}/containers/systemd
install -d %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd
# Install the ROS2 Rolling container file
install -m 644 %{_builddir}/qm-ros2-%{version}/subsystems/ros2/etc/containers/systemd/ros2.container \
%{buildroot}%{qm_sysconfdir}/containers/systemd/ros2.container
install -m 644 %{_builddir}/qm-ros2-%{version}/subsystems/ros2/etc/containers/systemd/ros2-rolling.container %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd/ros2-rolling.container
%files
%license LICENSE
%doc README.md SECURITY.md
%{qm_sysconfdir}/containers/systemd/ros2.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/ros2-rolling.container
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org> - 0.6.8-1
- Initial release of qm-ros2
- Initial release of qm-ros2-rolling

View File

@ -1,10 +1,10 @@
%global debug_package %{nil}
# Define the rootfs macros
%define qm_sysconfdir %{_sysconfdir}/qm
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-sound
Version: %{version}
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM containers to mount bind /dev/snd
License: GPL-2.0-only
@ -12,7 +12,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-sound-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage installs a drop-in configuration for QM containers,
@ -29,10 +29,9 @@ the container and nested containers.
# Install drop-in configuration for /dev/snd
# Create the directory for drop-in configurations
install -d %{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d
install -d %{buildroot}%{qm_sysconfdir}/containers/systemd
install -d %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd
install -m 644 %{_builddir}/qm-sound-%{version}/subsystems/sound/etc/containers/systemd/audio.container \
%{buildroot}%{qm_sysconfdir}/containers/systemd/audio.container
install -m 644 %{_builddir}/qm-sound-%{version}/subsystems/sound/etc/containers/systemd/audio.container %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd/audio.container
# Install the sound drop-in configuration file
install -m 644 %{_builddir}/qm-sound-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_snd.conf \
%{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_snd.conf
@ -41,7 +40,7 @@ install -m 644 %{_builddir}/qm-sound-%{version}/etc/containers/systemd/qm.contai
%license LICENSE
%doc README.md SECURITY.md
%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_snd.conf
%{qm_sysconfdir}/containers/systemd/audio.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/audio.container
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>

View File

@ -1,5 +1,8 @@
%global debug_package %{nil}
# Define rootfs macro for QM environment
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-text2speech
Version: 0
Release: 1%{?dist}
@ -9,9 +12,18 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-text2speech-%{version}.tar.gz
BuildArch: noarch
# Build requirements
BuildRequires: make
BuildRequires: podman
BuildRequires: selinux-policy
BuildRequires: selinux-policy-devel
# Runtime dependencies
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
Requires: qm-mount-bind-sound
Requires: selinux-policy >= %{_selinux_policy_version}
Requires: selinux-policy-base >= %{_selinux_policy_version}
Requires: podman
Requires: espeak
%description -n qm-text2speech
@ -25,7 +37,7 @@ This subpackage provides a drop-in configuration for the QM environment to enabl
%install
%post
dnf install --setopt=reposdir=/etc/yum.repos.d --installroot /usr/lib/qm/rootfs/ espeak-ng
dnf --setopt=reposdir=/etc/qm/yum.repos.d --installroot /usr/lib/qm/rootfs/ install espeak -y
%files
%license LICENSE
@ -33,4 +45,4 @@ dnf install --setopt=reposdir=/etc/yum.repos.d --installroot /usr/lib/qm/rootf
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>
- Initial standalone spec for the QM espeak subpackage.
- Initial standalone spec for the QM KVM subpackage.

View File

@ -9,7 +9,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-tty7-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage installs a drop-in configuration for QM containers to mount bind `/dev/tty7`.

View File

@ -1,6 +1,6 @@
%global debug_package %{nil}
Name: qm-mount-bind-ttyUSB0
Name: qm_mount_bind_ttyUSB0
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM containers to mount bind ttyUSB0
@ -9,7 +9,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-ttyUSB0-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This sub-package installs drop-in configurations for QM containers to mount bind ttyUSB0.

View File

@ -1,10 +1,10 @@
%global debug_package %{nil}
# Define the rootfs macros
%define qm_sysconfdir %{_sysconfdir}/qm
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-mount-bind-video
Version: %{version}
Version: 0
Release: 1%{?dist}
Summary: Drop-in configuration for QM containers to mount bind /dev/video
License: GPL-2.0-only
@ -12,7 +12,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-video-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This subpackage installs a drop-in configuration for QM containers to mount bind `/dev/video`.
@ -26,11 +26,10 @@ This subpackage installs a drop-in configuration for QM containers to mount bind
%install
# Create the directory for drop-in configurations
install -d %{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d
install -d %{buildroot}%{qm_sysconfdir}/containers/systemd
install -m 644 %{_builddir}/qm-video-%{version}/subsystems/video/etc/containers/systemd/rear-camera.container \
%{buildroot}%{qm_sysconfdir}/containers/systemd/rear-camera.container
install -d %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd
install -m 644 %{_builddir}/qm-video-%{version}/subsystems/video/etc/containers/systemd/rear-camera.container %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd/rear-camera.container
# Install the sound drop-in configuration file
install -m 644 %{_builddir}/qm-video-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_video.conf \
%{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_video.conf
@ -38,7 +37,7 @@ install -m 644 %{_builddir}/qm-video-%{version}/etc/containers/systemd/qm.contai
%license LICENSE
%doc README.md SECURITY.md
%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_video.conf
%{qm_sysconfdir}/containers/systemd/rear-camera.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/rear-camera.container
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>

View File

@ -1,9 +1,9 @@
# Define the rootfs macros
%define qm_sysconfdir %{_sysconfdir}/qm
%global rootfs_qm %{_prefix}/lib/qm/rootfs/
Name: qm-windowmanager
Version: %{version}
Version: 0
Release: 1%{?dist}
Summary: Optional Window Manager for QM environment
License: GPL-2.0-only
@ -11,7 +11,7 @@ URL: https://github.com/containers/qm
Source0: %{url}/archive/qm-windowmanager-%{version}.tar.gz
BuildArch: noarch
Requires: qm >= %{version}
Requires: qm = %{version}-%{release}
%description
This sub-package installs an experimental window manager for the QM environment.
@ -23,23 +23,23 @@ This sub-package installs an experimental window manager for the QM environment.
# Create the directory for drop-in configurations
install -d %{buildroot}/%{_sysconfdir}/pam.d/
install -d %{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d
install -d %{buildroot}%{qm_sysconfdir}/containers/systemd
install -d %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd
# Install the Window manager drop-in configuration file
install -m 644 %{_builddir}/qm-windowmanager-%{version}/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_window_manager.conf \
%{buildroot}%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_window_manager.conf
install -m 644 %{_builddir}/qm-windowmanager-%{version}/subsystems/windowmanager/etc/pam.d/wayland %{buildroot}/%{_sysconfdir}/pam.d/
install -m 644 %{_builddir}/qm-windowmanager-%{version}/subsystems/windowmanager/etc/containers/systemd/* %{buildroot}%{qm_sysconfdir}/containers/systemd/
install -m 644 %{_builddir}/qm-windowmanager-%{version}/subsystems/windowmanager/etc/containers/systemd/* %{buildroot}%{rootfs_qm}%{_sysconfdir}/containers/systemd/
%files
%license LICENSE
%doc README.md
%{_sysconfdir}/pam.d/wayland
%{_sysconfdir}/containers/systemd/qm.container.d/qm_dropin_mount_bind_window_manager.conf
%{qm_sysconfdir}/containers/systemd/gnome_mutter.container
%{qm_sysconfdir}/containers/systemd/session-activate.container
%{qm_sysconfdir}/containers/systemd/wayland-extra-devices.conf
%{qm_sysconfdir}/containers/systemd/weston_terminal.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/gnome_mutter.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/session-activate.container
%{rootfs_qm}%{_sysconfdir}/containers/systemd/wayland-extra-devices.conf
%{rootfs_qm}%{_sysconfdir}/containers/systemd/weston_terminal.container
%changelog
* Fri Jul 21 2023 RH Container Bot <rhcontainerbot@fedoraproject.org>

61
setup
View File

@ -35,41 +35,10 @@ CMDLINE_ARGUMENT_LIST=(
"skip-systemctl"
)
logger() {
{
local log_level="$1"
local message="$2"
local NC='\033[0m' # No Color
local log_col=$NC
} > /dev/null 2>&1
case "$log_level" in
INFO)
log_col='\033[0;36m' #BLUE
;;
WARNING)
log_col='\033[1;33m' #YELLOW
;;
ERROR)
log_col='\033[0;31m' #RED
;;
DEBUG)
log_col='\033[0;90m' #GREY
;;
SUCCESS)
log_col='\033[0;32m' #GREEN
;;
*)
echo -e "[\033[1;31mERROR\033[0m] Invalid log level: $log_level" >&2
return 1
;;
esac
echo -e "[$log_col${log_level}${NC}] $message"
}
root_check() {
if [ "$(id -u)" -ne 0 ];then
logger "WARNING" "Please run this script as root"
exit 1
echo "Please run this script as root"
exit 1
fi
}
@ -163,7 +132,7 @@ validate_qm_installation() {
for file in "${files[@]}"; do
if [[ ! -f "$file" ]]; then
logger "ERROR" "Exiting... '$file' not found. Try reinstall the QM package before continuing."
echo "Exiting... '$file' not found. Try reinstall the QM package before continue." >&2
exit 1
fi
done
@ -178,7 +147,7 @@ install() {
setupRW "${ROOTFS}" "${RWETCFS}" "${RWVARFS}"
EXTRA_FLAG=""
if [ "$ID" == "fedora" ] && [ "$VERSION_ID" -ge 41 ]; then
if grep -qi "^ID=fedora" /etc/os-release; then
EXTRA_FLAG="--use-host-config"
fi
@ -334,23 +303,15 @@ case "$1" in
if [ "$SYSTEMCTL_SKIP" == "N" ]; then
systemctl daemon-reload
systemctl start qm.service || {
logger "ERROR" "'systemctl start qm.service' has failed, see details below";
set +x
logger "DEBUG" "$(journalctl --no-pager -xu qm.service)"
set -x
exit 1;
}
if [ "$(systemctl is-active qm.service)" != "active" ]; then
logger "WARNING" "QM service is inactive, see details below:";
set +x
logger "DEBUG" "$(journalctl --no-pager -xu qm.service)"
set -x
exit 1
fi
systemctl start qm.service
if [ "$(systemctl is-active qm.service)" != "active" ]; then
journal=$(journalctl --no-pager -xu qm.service)
echo QM service is not up details:
echo "$journal"
exit 1
fi
else
/usr/libexec/podman/quadlet /run/systemd/generator/
fi
logger "SUCCESS" "Setup complete";
;;
esac

View File

@ -1,8 +1,7 @@
RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_DVB ?= ${ROOTDIR}/rpm/dvb/dvb.spec
PACKAGE_NAME = qm-mount-bind-dvb
SPECFILE_SUBPACKAGE_VIDEO ?= ${ROOTDIR}/rpm/dvb/dvb.spec
.PHONY: dist
dist: ## - Creates the QM dvb package
@ -25,8 +24,4 @@ dvb: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_DVB}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -0,0 +1,33 @@
RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_IMG_TEMPDIR ?= ${ROOTDIR}/rpm/img_tempdir/img_tempdir.spec
.PHONY: dist
dist: ## - Creates the QM img_tempdir package
cd $(ROOTDIR) && tar cvz \
--dereference \
--transform 's|subsystems/img_tempdir/Makefile|Makefile|' \
--transform 's|rpm/img_tempdir/img_tempdir.spec|img_tempdir.spec|' \
--transform s/qm/qm-img_tempdir-${VERSION}/ \
-f /tmp/qm-img_tempdir-${VERSION}.tar.gz \
../qm/rpm/img_tempdir/img_tempdir.spec \
../qm/subsystems/img_tempdir/Makefile \
../qm/tools/version-update \
../qm/VERSION \
../qm/README.md \
../qm/SECURITY.md \
../qm/LICENSE \
../qm/etc/qm/containers/containers.conf.d/qm_dropin_img_tempdir.conf
cd $(ROOTDIR) && mv /tmp/qm-img_tempdir-${VERSION}.tar.gz ./rpm
.PHONY: img_tempdir
img_tempdir: dist ## - Creates a local RPM package, useful for development
cd $(ROOTDIR) && mkdir -p ${RPM_TOPDIR}/{RPMS,SRPMS,BUILD,SOURCES}
cd $(ROOTDIR) && tools/version-update -v ${VERSION}
cd $(ROOTDIR) && cp ./rpm/qm-img_tempdir-${VERSION}.tar.gz ${RPM_TOPDIR}/SOURCES
rpmbuild -ba \
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_IMG_TEMPDIR}

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_INPUT ?= ${ROOTDIR}/rpm/input/input.spec
PACKAGE_NAME = qm-mount-bind-input
.PHONY: dist
dist: ## - Creates the QM input package
@ -25,7 +24,3 @@ input: dist ## - Creates a local RPM package, useful for developmen
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_INPUT}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -0,0 +1,18 @@
# ContainerFile used to create the image available at quay.io/qm-images/kvm:latest
#
# How to build
# ==================
# podman login quay.io
# use build_kvm_container.sh to build container
# podman push quay.io/qm-images/kvm:latest
FROM fedora-minimal:latest
ENV PASSWORD_FEDORA_USER=fedora
RUN dnf install qemu-system-$(arch) -y \
&& dnf clean all && rm -rf /var/cache/dnf
COPY ./Fedora-Cloud-Base-Generic.qcow2 /var/lib/libvirt/images/
# Set container stay alive
ENTRYPOINT ["/usr/bin/qemu-system-x86_64","-smp","12","-enable-kvm","-m","2G","-machine","q35","-cpu","host","-device","virtio-net-pci,netdev=n0,mac=FE:30:26:a6:91:2d","-netdev","user,id=n0,net=10.0.2.0/24,hostfwd=tcp::2226-:22","-drive","file=/var/lib/libvirt/images/Fedora-Cloud-Base-Generic.qcow2,index=0,media=disk,format=qcow2,if=virtio,snapshot=off","-nographic"]

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_IMG_KVM ?= ${ROOTDIR}/rpm/kvm/qm-kvm.spec
PACKAGE_NAME = qm-kvm
.PHONY: dist
dist: ## - Creates the QM kvm package
@ -19,9 +18,7 @@ dist: ## - Creates the QM kvm package
../qm/README.md \
../qm/SECURITY.md \
../qm/LICENSE \
../qm/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_kvm.conf \
../qm/subsystems/kvm/etc/containers/systemd/kvm.container
../qm/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_kvm.conf
cd ${ROOTDIR} && mv /tmp/qm-kvm-${VERSION}.tar.gz ./rpm
.PHONY: kvm
@ -33,7 +30,4 @@ kvm: dist ## - Creates a local RPM kvm package, useful for developme
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_IMG_KVM}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -0,0 +1,21 @@
#!/usr/bin/bash
# Install required repos
dnf install guestfs-tools \
curl \
perl -y
# Download fedora cloud image
curl -Lo ./Fedora-Cloud-Base-Generic.qcow2 https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/"$(arch)"/images/Fedora-Cloud-Base-Generic-41-1.4."$(arch)".qcow2
# Customize user:pass
export LIBGUESTFS_BACKEND=direct && \
virt-customize -a ./Fedora-Cloud-Base-Generic.qcow2 \
--edit '/etc/ssh/sshd_config: s/#PasswordAuthentication.*/PasswordAuthentication yes/' \
--uninstall cloud-init \
--firstboot-command "useradd -m -s /bin/bash -G wheel fedora" \
--firstboot-command "echo 'fedora:fedora' | chpasswd"
# Container build
podman build -t quay.io/qm-images/kvm:latest -f ContainerFile

View File

@ -4,8 +4,6 @@ After=network.target
[Container]
Image=quay.io/qm-images/kvm:latest
ContainerName=kvm-container
AddDevice=-/dev/kvm
[Install]
WantedBy=multi-user.target

View File

@ -1,23 +0,0 @@
# ContainerFile used to create the image available at quay.io/qm-images/kvm:latest
#
# How to build
# ==================
# podman login quay.io
# use build_kvm_container.sh to build container
# podman push quay.io/qm-images/kvm:latest
FROM fedora-minimal:latest
ARG ARCH_QEMU
ENV PASSWORD_FEDORA_USER=fedora
RUN echo "Using QEMU architecture: ${ARCH_QEMU}"
ENV ARCH_QEMU=${ARCH_QEMU}
RUN dnf install qemu-system-${ARCH_QEMU} -y \
&& dnf clean all && rm -rf /var/cache/dnf
COPY ./Fedora-Cloud-Base-Generic.qcow2 /var/lib/libvirt/images/
# Set container stay alive
ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/qemu-system-${ARCH_QEMU} -smp 8 -enable-kvm -m 700M -machine q35 -cpu host -device virtio-net-pci,netdev=n0,mac=FE:30:26:a6:91:2d -netdev user,id=n0,net=10.0.2.0/24,hostfwd=tcp::2226-:22 -drive file=/var/lib/libvirt/images/Fedora-Cloud-Base-Generic.qcow2,index=0,media=disk,format=qcow2,if=virtio,snapshot=off -nographic"]

View File

@ -1,43 +0,0 @@
#!/usr/bin/bash
# Install required repos
sudo dnf -y install guestfs-tools curl perl qemu-user-static
ARCHS=("amd64" "aarch64")
IMAGE_NAME="kvm"
TAG="latest"
MANIFEST_NAME="${IMAGE_NAME}-manifest:${TAG}"
FEDORA_USER_PASSWORD=${FEDORA_USER_PASSWORD:-$(openssl rand -base64 12)}
#IMG_REG=quay.io
#IMG_ORG=qm-images
rm -f ./Fedora-Cloud-Base-Generic.qcow2
podman manifest rm "$MANIFEST_NAME"
podman manifest create "$MANIFEST_NAME" || exit 1
for ARCH in "${ARCHS[@]}"; do
ARCH_QEMU=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "$ARCH")
curl -Lo ./Fedora-Cloud-Base-Generic.qcow2 "https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/${ARCH_QEMU}/images/Fedora-Cloud-Base-Generic-41-1.4.${ARCH_QEMU}.qcow2"
# Customize user:pass
export LIBGUESTFS_BACKEND=direct && \
virt-customize -a ./Fedora-Cloud-Base-Generic.qcow2 \
--edit '/etc/ssh/sshd_config: s/#PasswordAuthentication.*/PasswordAuthentication yes/' \
--firstboot-command 'dnf remove -y cloud-init' \
--firstboot-command "useradd -m -s /bin/bash -G wheel fedora" \
--firstboot-command "echo fedora:$FEDORA_USER_PASSWORD | chpasswd"
echo "Adding ${IMAGE_NAME}:${ARCH} to the manifest"
podman build \
--arch "${ARCH}" \
--build-arg ARCH_QEMU="${ARCH_QEMU}" \
--manifest ${MANIFEST_NAME} \
-f ContainerFile \
-t "${IMAGE_NAME}:${ARCH}"
rm -f ./Fedora-Cloud-Base-Generic.qcow2
done
#podman login --username "${REG_USERNAME}" --password "${REG_PASSWORD}" "${REG_URL}"
#podman push localhost/kvm-manifest quay.io/qm-images/kvm:latest

View File

@ -1,8 +1,7 @@
RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_RADIO ?= ${ROOTDIR}/rpm/radio/radio.spec
PACKAGE_NAME = qm-mount-bind-radio
SPECFILE_SUBPACKAGE_VIDEO ?= ${ROOTDIR}/rpm/radio/radio.spec
.PHONY: dist
dist: ## - Creates the QM radio package
@ -13,7 +12,7 @@ dist: ## - Creates the QM radio package
../qm/README.md \
../qm/SECURITY.md \
../qm/LICENSE \
../qm/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_radio.conf
../qm/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_radio.conf
cd $(ROOTDIR) && mv /tmp/qm-radio-${VERSION}.tar.gz ./rpm
@ -26,7 +25,4 @@ radio: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_RADIO}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_ROS2_ROLLING ?= ${ROOTDIR}/rpm/ros2/ros2_rolling.spec
PACKAGE_NAME = qm-ros2
.PHONY: dist
dist: ## - Creates the QM ros2 package
@ -19,7 +18,7 @@ dist: ## - Creates the QM ros2 package
../qm/README.md \
../qm/SECURITY.md \
../qm/LICENSE \
../qm/subsystems/ros2/etc/containers/systemd/ros2.container
../qm/subsystems/ros2/etc/containers/systemd/ros2-rolling.container
cd $(ROOTDIR) && mv /tmp/qm-ros2-${VERSION}.tar.gz ./rpm
@ -32,7 +31,4 @@ ros2: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_ROS2_ROLLING}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -3,8 +3,7 @@ Description=ROS 2 Container Development env
After=network.target
[Container]
Image=quay.io/fedora-sig-robotics/ros2:jazzy-cs9
Exec=sleep infinity
Image=quay.io/qm-images/ros2:rolling
[Install]
WantedBy=multi-user.target

View File

@ -2,25 +2,18 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_SOUND ?= ${ROOTDIR}/rpm/sound/sound.spec
PACKAGE_NAME = qm-sound
.PHONY: dist
dist: ## - Creates the QM sound package
cd $(ROOTDIR) && tar cvz \
--dereference \
--transform 's|subsystems/kvm/Makefile|Makefile|' \
--transform 's|rpm/sound/sound.spec|qm-sound.spec|' \
--transform 's|qm|qm-sound-${VERSION}|' \
--transform s/qm/qm-sound-${VERSION}/ \
-f /tmp/qm-sound-${VERSION}.tar.gz \
../qm/rpm/sound/sound.spec \
../qm/subsystems/sound/Makefile \
../qm/tools/version-update \
../qm/README.md \
../qm/SECURITY.md \
../qm/LICENSE \
../qm/etc/containers/systemd/qm.container.d/qm_dropin_mount_bind_snd.conf \
../qm/subsystems/sound/etc/containers/systemd/audio.container
cd $(ROOTDIR) && mv /tmp/qm-sound-${VERSION}.tar.gz ./rpm
.PHONY: sound
@ -32,7 +25,4 @@ sound: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_SOUND}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -4,8 +4,6 @@ After=network.target
[Container]
Image=quay.io/qm-images/audio:latest
Network=host
AddDevice=/dev/snd
[Install]
WantedBy=multi-user.target

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_TEXT2SPEECH ?= ${ROOTDIR}/rpm/text2speech/text2speech.spec
PACKAGE_NAME = qm-text2speech
.PHONY: dist
dist: ## - Creates the QM input package
@ -31,7 +30,3 @@ text2speech: dist ## - Creates a local RPM package, useful for develo
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_TEXT2SPEECH}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_TTY7 ?= ${ROOTDIR}/rpm/tty7/tty7.spec
PACKAGE_NAME = qm-mount-bind-tty7
.PHONY: dist
dist: ## - Creates the QM tty7 package
@ -31,7 +30,4 @@ tty7: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_TTY7}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_TTYUSB0 ?= ${ROOTDIR}/rpm/ttyUSB0/ttyUSB0.spec
PACKAGE_NAME = qm-mount-bind-ttyUSB0
.PHONY: dist
dist: ## - Creates the QM ttyUSB0 package
@ -31,7 +30,4 @@ ttyUSB0: dist ## - Creates a local RPM package, useful for developme
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_TTYUSB0}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_VIDEO ?= ${ROOTDIR}/rpm/video/video.spec
PACKAGE_NAME = qm-mount-bind-video
.PHONY: dist
dist: ## - Creates the QM video package
@ -32,7 +31,4 @@ video: dist ## - Creates a local RPM package, useful for development
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_VIDEO}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -12,5 +12,4 @@ WantedBy=multi-user.target
[Container]
Image=quay.io/qm-images/multimedia:latest
Exec=fswebcam -r 1024x768 --jpeg 100 /tmp/screenshot.jpg
Volume=/var/tmp:/tmp:Z
AddDevice=-/dev/video0
Volume=/tmp:/tmp

View File

@ -2,7 +2,6 @@ RPM_TOPDIR ?= $(PWD)/rpmbuild
VERSION ?= $(shell cat VERSION)
ROOTDIR ?= $(PWD)
SPECFILE_SUBPACKAGE_IMG_WINDOWMANAGER ?= ${ROOTDIR}/rpm/windowmanager/windowmanager.spec
PACKAGE_NAME = qm-windowmanager
.PHONY: dist
dist: ## - Creates the QM windowmanager package
@ -29,7 +28,4 @@ windowmanager: dist ## - Creates a local windowmanager package, useful f
--define="_topdir ${RPM_TOPDIR}" \
--define="version ${VERSION}" \
${SPECFILE_SUBPACKAGE_IMG_WINDOWMANAGER}
if [ ! -f ${RPM_TOPDIR}/RPMS/noarch/${PACKAGE_NAME}-${VERSION}*.noarch.rpm ]; then \
echo "rpmbuild failed to build: ${PACKAGE_NAME}"; \
exit 1; \
fi

View File

@ -9,6 +9,6 @@ COPR_URL="https://download.copr.fedorainfracloud.org/results/${USE_QM_COPR}/epel
EXTRA_REPOS='extra_repos=[{"id":"qm_build","baseurl":"'"$COPR_URL"'"}]'
# Run AIB in container
curl -o auto-image-builder.sh "https://gitlab.com/CentOS/automotive/src/automotive-image-builder/-/raw/main/auto-image-builder.sh?ref_type=heads"
curl -o auto-image-builder.sh "https://gitlab.com/CentOS/automotive/sample-images/-/raw/main/auto-image-builder.sh?ref_type=heads"
#shellcheck disable=SC2027,SC2090,SC2086
/bin/bash auto-image-builder.sh build --export qcow2 --define "'"$EXTRA_REPOS"'" qm.aib.yml qm.qcow2

View File

@ -74,7 +74,7 @@ install_qm_rpms() {
fi
fi
dnf install -y bluechi-ctl bluechi-agent bluechi-controller bluechi-is-online qm hostname
dnf install -y bluechi-ctl bluechi-agent bluechi-controller qm hostname
}
set_qm_rlimits() {

View File

@ -51,8 +51,8 @@ ${container_target}:/tmp/container-${srv}.container"
target_service_file=$(podman exec ${container_target} systemctl show -P SourcePath qm.service)
# START: remove DropCapability to run nested container
# TBD: use drop-in files to update qm.service
podman exec -it ${container_target} bash -c "sed -i '/^\s*DropCapability=/ d' \"${target_service_file}\""
if_error_exit "unable to remove DropCapability=<caps> in qm.container"
podman exec -it ${container_target} bash -c "sed -i '/^\s*DropCapability=sys_resource/ d' \"${target_service_file}\""
if_error_exit "unable to remove DropCapability=sys_resource in qm.container"
podman exec -it ${container_target} systemctl daemon-reload
if_error_exit "unable to execute daemon-reload"

View File

@ -1,4 +1,3 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -6,55 +5,24 @@
#include <errno.h>
#include <string.h>
int main(int argc, char *argv[]) {
int main() {
int pid = getpid();
int policy; // Desired scheduling policy
char *policy_name;
int policy = SCHED_FIFO; // Desired scheduling policy
struct sched_param param;
if (argc == 2)
{
policy_name = argv[1];
if (strcmp(policy_name, "SCHED_OTHER")==0) {
policy = SCHED_OTHER;
} else if (strcmp(policy_name, "SCHED_BATCH")==0) {
policy = SCHED_BATCH;
} else if (strcmp(policy_name, "SCHED_IDLE")==0) {
policy = SCHED_IDLE;
} else if (strcmp(policy_name, "SCHED_FIFO")==0) {
policy = SCHED_FIFO;
} else if (strcmp(policy_name, "SCHED_RR")==0) {
policy = SCHED_RR;
} else {
printf("Unknown policy.\n");
return EXIT_FAILURE;
}
}
else if (argc > 2)
{
printf("Too many policies supplied.\n");
return EXIT_FAILURE;
}
else
{
printf("One policy expected.\n");
return EXIT_FAILURE;
}
// Assign the maximum priority for the policy
// Assign the maximum priority for the SCHED_FIFO policy
param.sched_priority = sched_get_priority_max(policy);
if (param.sched_priority == -1) {
fprintf(stderr, "Failed to get max priority for %s: %s\n", policy_name, strerror(errno));
fprintf(stderr, "Failed to get max priority for SCHED_FIFO: %s\n", strerror(errno));
return EXIT_FAILURE;
}
// Attempt to set the scheduling policy and priority
if (sched_setscheduler(pid, policy, &param) == -1) {
printf("sched_setscheduler(%s) failed: errno=%d (%s)", policy_name, errno, strerror(errno));
fprintf(stderr, "Failed to set scheduler: %s\n", strerror(errno));
return EXIT_FAILURE;
} else {
printf("sched_setscheduler(%s) succeeded.", policy_name);
return EXIT_SUCCESS;
}
printf("Scheduler set to SCHED_FIFO with priority %d\n", param.sched_priority);
return EXIT_SUCCESS;
}

View File

@ -10,6 +10,8 @@ fi
. ../common/prepare.sh
export QM_HOST_REGISTRY_DIR="/var/qm/lib/containers/registry"
export QM_REGISTRY_DIR="/var/lib/containers/registry"
export NUMBER_OF_NODES="${NUMBER_OF_NODES:-2}"
WAIT_BLUECHI_AGENT_CONNECT="${WAIT_BLUECHI_AGENT_CONNECT:-5}"
@ -24,13 +26,12 @@ Description=bluechi-tester-X
After=local-fs.target
[Container]
Image=quay.io/centos-sig-automotive/ffi-tools:latest
Image=dir:/var/lib/containers/registry/tools-ffi:latest
Exec=/root/tests/FFI/bin/bluechi-tester --url="tcp:host=${controller_host_ip},port=842" \
--nodename=bluechi-tester-X \
--numbersignals=11111111 \
--signal="JobDone"
Network=host
StopTimeout=1
EOF
sed -i -e "s/tester-X/tester-${i}/g" "/etc/qm/containers/systemd/bluechi-tester-${i}.container"
@ -78,9 +79,8 @@ get_qm_network_mode(){
echo "${qm_network_mode}"
}
trap disk_cleanup EXIT
prepare_test
reload_config
init_ffi
prepare_images
# Assign value to ${controller_host_ip} according to qm network mode
if [ "$(get_qm_network_mode)" == "private" ]; then

View File

@ -1,16 +0,0 @@
[Unit]
Description=Container ffi-tools with precompiled checks
After=local-fs.target
[Container]
ContainerName=ffi-qm
Image=quay.io/centos-sig-automotive/ffi-tools:latest
Exec=sleep infinity
StopTimeout=1
[Install]
# Start by default on qm boot
WantedBy=multi-user.target default.target
[Service]
Restart=always

View File

@ -2,8 +2,13 @@
# shellcheck disable=SC1091
. ../../e2e/lib/utils
export DROP_IN_DIR="/etc/containers/systemd/qm.container.d/"
DROP_IN_DIR="/etc/containers/systemd/qm.container.d/"
OSTREE_PATH="/run/ostree"
export QM_HOST_REGISTRY_DIR="/var/qm/lib/containers/registry"
export QM_REGISTRY_DIR="/var/lib/containers/registry"
export QM_TMP_DIR="/var/tmp.dir"
export CONTAINERS_CONF_DIR="/etc/qm/containers/containers.conf.d"
export QM_IMAGE_TMP_DIR_CONF="qm_image_tmp_dir.conf"
# Checks if the system is running under OSTree.
# This function determines if the system is using OSTree by checking for the
@ -33,12 +38,12 @@ prepare_test() {
}
disk_cleanup() {
exec_cmd "podman exec -it qm /bin/bash -c \"podman rmi -f --all\""
# Clean large size files created by tests inside qm part
remove_file=$(find /var/qm -size +2G)
exec_cmd "rm -rf $remove_file"
# Remove all containers in qm (don't care about stop in clean-up)
exec_cmd "podman exec -it qm /usr/bin/podman rm -af"
if test -d "${DROP_IN_DIR}"; then
# Clean drop-in files used for tests
if test -d "${DROP_IN_DIR=}"; then
exec_cmd "rm -rf ${DROP_IN_DIR}"
fi
exec_cmd "systemctl daemon-reload"
@ -53,13 +58,60 @@ reload_config() {
exec_cmd "systemctl restart qm"
}
running_container_in_qm() {
while true; do
if podman exec qm /usr/bin/systemctl is-active ffi-qm -q; then
info_message "ffi-qm container inside qm is fully started"
break
fi
sleep 1
done
info_message "qm was started: $(systemctl status qm | grep Active | cut -d ';' -f 2)"
prepare_images() {
# Update container image_copy_tmp_dir if the image is an OStree.
# Default location for storing temporary container image content. Can be overridden with the TMPDIR environment
# variable. If you specify "storage", then the location of the
# container/storage tmp directory will be used.
# By default image_copy_tmp_dir="/var/tmp"
# This is a work around and it should not be used constantly
# This script checks if the directory /run/ostree exists.
# If it does, it executes the following commands:
# 1. Creates the directory /var/qm/tmp.dir if it does not already exist.
# 2. Creates the directory /etc/qm/containers/containers.conf.d if it does not already exist.
# 3. Writes a configuration file qm_image_tmp_dir.conf in /etc/qm/containers/containers.conf.d
# with the content specifying the temporary directory for image copying as /var/tmp.dir.
if is_ostree; then
exec_cmd "mkdir -p /var/qm/tmp.dir"
exec_cmd "mkdir -p ${CONTAINERS_CONF_DIR}"
exec_cmd "echo -e '[engine]\nimage_copy_tmp_dir=\"${QM_TMP_DIR}\"' > ${CONTAINERS_CONF_DIR}/${QM_IMAGE_TMP_DIR_CONF}"
fi
exec_cmd "podman pull quay.io/centos-sig-automotive/ffi-tools:latest"
# Copy container image registry to /var/qm/lib/containers
image_id=$(podman images | grep quay.io/centos-sig-automotive/ffi-tools | awk -F " " '{print $3}')
if [ -d "${QM_HOST_REGISTRY_DIR}" ]; then
rm -rf ${QM_HOST_REGISTRY_DIR}
fi
exec_cmd "mkdir -p ${QM_HOST_REGISTRY_DIR}"
exec_cmd "podman push ${image_id} dir:${QM_HOST_REGISTRY_DIR}/tools-ffi:latest"
# Remove image to save /var space
exec_cmd "podman rmi -f ${image_id}"
}
run_container_in_qm() {
local container_name
local tmp_image_dir
local run_ctr_in_qm
# Clean tmp image directory
tmp_image_dir=$(podman info | grep CopyTmp | awk -F":" '{print $2}')
container_name="${1}"
exec_cmd "podman exec -it qm /bin/bash -c \
\"rm -rf ${tmp_image_dir}/*\""
run_ctr_in_qm="podman exec -it qm /bin/bash -c \
\"podman run -d --net host --replace --name ${container_name} \
dir:${QM_REGISTRY_DIR}/tools-ffi:latest \
tail -f /dev/null\""
exec_cmd "${run_ctr_in_qm}"
}
# Agregates 3 functions from this tool to a single init_ffi function, used to initialize environments before tests with a single function, instead of using three separate functions.
init_ffi() {
disk_cleanup
prepare_test
reload_config
}

View File

@ -5,18 +5,20 @@
expected_result="sched_setattr failed: Operation not permitted"
trap disk_cleanup EXIT
disk_cleanup
prepare_test
reload_config
running_container_in_qm
prepare_images
run_container_in_qm "ffi-qm"
return_from_sched_setattr=$(podman exec -it qm /usr/bin/podman exec -it ffi-qm ./QM/execute_sched_setattr)
return_from_sched_setattr=$(podman exec -it qm /bin/bash -c \
'podman exec -it ffi-qm ./QM/execute_sched_setattr')
# shellcheck disable=SC2076
if [[ "${return_from_sched_setattr}" =~ "${expected_result}" ]]; then
info_message "PASS: QM not allow SCHED_DEADLINE be set via sched_setattr() syscall."
info_message "QM not allow SCHED_DEADLINE be set via sched_setattr() syscall."
else
info_message "FAIL: SCHED_DEADLINE can not be set via sched_setattr() syscall in QM."
info_message "Failure: SCHED_DEADLINE can not be set via sched_setattr() syscall in QM."
exit 1
fi

View File

@ -3,44 +3,21 @@
# shellcheck source=tests/ffi/common/prepare.sh
. ../common/prepare.sh
policy_arr=(SCHED_OTHER SCHED_BATCH SCHED_IDLE SCHED_FIFO SCHED_RR)
num_of_failed_policy=0
expected_result="Failed to set scheduler: Operation not permitted"
trap disk_cleanup EXIT
disk_cleanup
prepare_test
reload_config
running_container_in_qm
# Copy the test from ffi-qm container to qm container
podman exec -it qm /usr/bin/podman cp ffi-qm:/root/tests/FFI/bin/QM/test_sched_setscheduler /var/
prepare_images
run_container_in_qm "ffi-qm"
for policy in "${policy_arr[@]}"; do
# Run the test inside qm container
return_from_setscheduler=$(podman exec -it qm ./var/test_sched_setscheduler "$policy")
return_from_setscheduler=$(podman exec -it qm /bin/bash -c \
'podman exec -it ffi-qm ./QM/test_sched_setscheduler')
# Assign the expected result according to the policy
if [[ "$policy" == "SCHED_OTHER" || "$policy" == "SCHED_BATCH" || "$policy" == "SCHED_IDLE" ]]; then
expected_result="sched_setscheduler($policy) succeeded."
elif [[ "$policy" == "SCHED_FIFO" || "$policy" == "SCHED_RR" ]]; then
expected_result="sched_setscheduler($policy) failed: errno=38 (Function not implemented)"
fi
# Check that the result is the same as expected
if [[ "${return_from_setscheduler}" == "${expected_result}" ]]; then
info_message "$expected_result"
info_message "PASS: The result of sched_setscheduler($policy) is as expected in QM."
else
info_message "$return_from_setscheduler"
info_message "FAIL: The result of sched_setscheduler($policy) is not what is expected in QM."
((num_of_failed_policy++))
fi
done
# If there is a failed policy, then this test returns failure
if [[ $num_of_failed_policy -gt 0 ]]; then
info_message "FAIL: sched_setscheduler() test failed."
exit 1
if [[ "${return_from_setscheduler}" =~ ${expected_result} ]]; then
info_message "set_scheduler() syscall denied in QM."
else
info_message "PASS: sched_setscheduler() test passed."
exit 0
info_message "set_scheduler() syscall can be executed in QM."
exit 1
fi

View File

@ -1,4 +1,4 @@
summary: Test for separate var partition for qm
summary: Test is calling systemd as stand alone test
test: /bin/bash ./test.sh
duration: 10m
tag: [ffi, NoRenesas]

View File

@ -5,57 +5,46 @@
. ../common/prepare.sh
check_var_partition(){
name_of_qm_var_partition="part /var/qm"
# In the ostree image
if stat /run/ostree-booted > /dev/null 2>&1; then
name_of_qm_var_partition="part /var"
qm_var_partition="part /var"
else
# In the centos cloud image
local release_id
release_id=$(grep -oP '(?<=^ID=)\w+' <<< "$(tr -d '"' < /etc/os-release)")
if [[ "$release_id" == "centos" ]]; then
name_of_qm_var_partition="part /usr/lib/qm/rootfs/var"
fi
qm_var_partition="part /usr/lib/qm/rootfs/var"
fi
# Prints all available block devices to make it easier to debug
exec_cmd "lsblk"
exec_cmd "df -kh"
# If there is no separate /var partition this test will terminate early
if [[ "$(lsblk -o 'MAJ:MIN,TYPE,MOUNTPOINTS')" =~ ${name_of_qm_var_partition} ]]; then
if [[ "$(lsblk -o 'MAJ:MIN,TYPE,MOUNTPOINTS')" =~ ${qm_var_partition} ]]; then
info_message "A separate /var partition was detected on the image."
else
lsblk
df -kh
info_message "FAIL: No separate /var partition was detected on the image."
info_message "Test terminated, it requires a separate /var disk partition for QM to run this test."
exit 1
fi
}
set_PodmanArgs(){
podmanArgs_of_qm=$(grep "PodmanArgs" /usr/share/containers/systemd/qm.container)
if [ -n "$podmanArgs_of_qm" ]; then
podmanArgs_of_qm=$podmanArgs_of_qm" --memory 5G"
else
podmanArgs_of_qm="--memory 5G"
fi
}
check_var_partition
trap disk_cleanup EXIT
disk_cleanup
prepare_test
set_PodmanArgs
cat << EOF > "${DROP_IN_DIR}"/oom.conf
[Service]
OOMScoreAdjust=
OOMScoreAdjust=1000
[Container]
PodmanArgs=
PodmanArgs=${podmanArgs_of_qm}
PodmanArgs=--pids-limit=-1 --security-opt seccomp=/usr/share/qm/seccomp-no-rt.json --security-opt label=nested --security-opt unmask=all --memory 5G
EOF
reload_config
prepare_images
exec_cmd "podman exec -it qm /bin/bash -c \
'podman run -d --replace --name ffi-qm \
quay.io/centos-sig-automotive/ffi-tools:latest \
tail -f /dev/null'"
running_container_in_qm
exec_cmd "podman exec -it qm /bin/bash -c \
'podman exec -it ffi-qm ./QM/file-allocate'"

View File

@ -6,4 +6,3 @@ require:
pattern:
- /tests/e2e/lib/utils
- /tests/ffi/common/prepare.sh
- /tests/ffi/common/ffi-qm.container

View File

@ -1,4 +1,4 @@
summary: Test kernel OOM kills qm container on high score processes
summary: Test is calling systemd as stand alone test
test: /bin/bash ./test.sh
duration: 25m
tag: ffi

View File

@ -4,19 +4,27 @@
. ../common/prepare.sh
trap disk_cleanup EXIT
disk_cleanup
prepare_test
cat << EOF > "${DROP_IN_DIR}"/oom.conf
[Service]
OOMScoreAdjust=
OOMScoreAdjust=1000
EOF
reload_config
prepare_images
exec_cmd "podman run -d --rm --replace -d --name ffi-asil \
quay.io/centos-sig-automotive/ffi-tools:latest \
./ASIL/20_percent_memory_eat > /dev/null"
reload_config
running_container_in_qm
podman exec qm podman exec ffi-qm ./QM/90_percent_memory_eat > /dev/null
podman exec -it qm /bin/bash -c \
"podman run --replace --name ffi-qm dir:${QM_REGISTRY_DIR}/tools-ffi:latest \
./QM/90_percent_memory_eat > /dev/null"
if [ $? -eq 137 ]; then
info_message "ffi-qm was killed by SIGKILL"
echo ffi-qm was killed by SIGKILL
fi
exec_cmd "systemctl status qm --no-pager | grep \"qm.service: A process of this unit has been killed\""

View File

@ -1,20 +1,22 @@
#!/bin/bash -uvx
#!/bin/bash -euvx
# shellcheck disable=SC1091
. ../common/prepare.sh
trap disk_cleanup EXIT
disk_cleanup
prepare_test
reload_config
# Download ffi-tools container and push ffi-tools image into QM registry
prepare_images
# Run the ffi-tools container in qm vm
running_container_in_qm
run_container_in_qm ffi-qm
# Get result message of './modprobe_module'
msg=$(podman exec -it qm /usr/bin/podman exec -it ffi-qm ./modprobe_module 2>&1)
info_message "Output is: $msg"
msg=$(podman exec -it qm /bin/bash -c \
"podman exec ffi-qm ./modprobe_module 2>&1")
# Check result message displays right.
if grep -eq "modprobe: FATAL: Module ext4 not found in directory /lib/modules/*" "$msg"; then

View File

@ -16,9 +16,10 @@
. ../common/prepare.sh
trap disk_cleanup EXIT
disk_cleanup
prepare_test
reload_config
prepare_images
# Function to retrieve the PID with retries for a container
get_pid_with_retries() {
@ -53,7 +54,8 @@ get_oom_score_adj() {
}
# Start the FFI container inside qm
running_container_in_qm
podman exec -it qm /bin/bash -c \
"podman run -d --replace --name ffi-qm dir:${QM_REGISTRY_DIR}/tools-ffi:latest /usr/bin/sleep infinity > /dev/null"
# Check if ffi-qm container started successfully
QM_FFI_STATUS=$(podman exec -it qm /bin/bash -c "podman inspect ffi-qm --format '{{.State.Status}}'" | tr -d '\r')

View File

@ -3,9 +3,8 @@
# shellcheck disable=SC1091
. ../common/prepare.sh
trap disk_cleanup EXIT
prepare_test
reload_config
# init_ffi uses 3in1 function from common.sh to initialize the environment before tests.
init_ffi
# Declare global variables and initialize to "".
NESTED_NAME=""
@ -18,8 +17,9 @@ NESTED_STATUS=""
# NESTED_NAME: The nested container name in the QM container.
# NESTED_STATUS: The nested container status in the QM container.
create_nested() {
prepare_images
local nested_container_name="ffi-qm"
running_container_in_qm
run_container_in_qm "${nested_container_name}"
NESTED_NAME=$(podman exec -it qm bash -c "podman inspect ${nested_container_name} --format '{{.Name}}'")
if_error_exit "An error occured: failed to extract Name parameter of container from inside of QM."
echo "Container name is: ${NESTED_NAME}"

View File

@ -4,15 +4,19 @@
. ../common/prepare.sh
trap disk_cleanup EXIT
disk_cleanup
prepare_test
reload_config
# Download ffi-tools container and push ffi-tools image into QM registry
prepare_images
# Run the ffi-tools container in qm vm
running_container_in_qm
run_container_in_qm ffi-qm
# Get numbers of sysctl permission denied
sysctl_num=$(podman exec qm /usr/bin/podman exec ffi-qm ./setsysctl 2>&1 | grep -c "sysctl: permission denied on key")
sysctl_num=$(podman exec qm /bin/bash -c \
"podman exec ffi-qm ./setsysctl 2>&1" | grep -c "sysctl: permission denied on key")
# We execute 'X' sysctl call(s) inside a nested container running in a QM environment
# to determine if changes are allowed, which should be denied for:
@ -20,6 +24,6 @@ sysctl_num=$(podman exec qm /usr/bin/podman exec ffi-qm ./setsysctl 2>&1 | grep
# - Virtual memory subsystem
SYSCTL_DENIED_COUNT=5
if [ "$sysctl_num" -eq "${SYSCTL_DENIED_COUNT}" ];then
info_message "PASS: Attempt to change OS level are denied successfully inside QM container."
info_message "Attempt to change OS level are denied successfully inside QM container."
exit 0
fi

View File

@ -1,7 +0,0 @@
summary: Test libkrun in qm
test: /bin/bash ./check_libkrun.sh
duration: 10m
tier: 0
tag: [kvm,setup]
framework: shell

View File

@ -1,26 +0,0 @@
#!/bin/bash -x
# shellcheck disable=SC1091
source ../../e2e/lib/utils
enable_repo() {
info_message "enable_repo(): enable repo"
exec_cmd "cd /etc/yum.repos.d/"
exec_cmd "dnf copr enable -y copr.fedorainfracloud.org/@centos-automotive-sig/libkrun centos-stream-9-$(arch)"
}
install_libkrun() {
info_message "install_libkrun(): install libkrun and crun-krun"
exec_cmd "dnf install --setopt=reposdir=/etc/yum.repos.d --installroot=/usr/lib/qm/rootfs -y libkrun crun-krun"
}
check_libkrun() {
info_message "check_libkrun(): run virtualization-isolated containers."
exec_cmd "podman exec -it qm podman run --runtime=krun --rm -it alpine echo 'Hello libkrun.'"
info_message "PASS: libkrun runs successfully."
}
enable_repo
install_libkrun
check_libkrun

View File

@ -0,0 +1,6 @@
summary: Test bluechi-controller is active and bluechi-agent is online
test: /bin/bash ./check_bluechi_controller_is_ok.sh
duration: 10m
tier: 0
framework: shell
id: 44d1f92b-2885-49d3-900a-23cde296c9d8

View File

@ -0,0 +1,33 @@
#!/bin/bash -euvx
# shellcheck disable=SC1091
source ../e2e/lib/utils
# Verify bluechi-controller is up and bluechictl is ok
check_bluechi_controller_is_ok(){
if [ "$(systemctl is-active bluechi-controller)" == "active" ]; then
info_message "check_bluechi_controller_is_ok(): bluechi-controller is active."
info_message "PASS: check_bluechi_controller_is_ok()"
else
info_message "FAIL: check_bluechi_controller_is_ok(): bluechi-controller is not active."
exit 1
fi
regex_qm_localrootfs="qm.localrootfs * \| online"
regex_ASIL_localrootfs="localrootfs * \| online"
if [[ ! "$(bluechictl status)" =~ ${regex_qm_localrootfs} ]]; then
info_message "FAIL: check_bluechi_controller_is_ok: Checking QM bluechi-agent online failed.\n $(bluechictl status)"
exit 1
elif [[ ! "$(bluechictl status)" =~ ${regex_ASIL_localrootfs} ]]; then
info_message "FAIL: check_bluechi_controller_is_ok: Checking host bluechi-agent online failed.\n $(bluechictl status)"
exit 1
else
info_message "check_bluechi_controller_is_ok: QM bluechi-agent is online."
info_message "check_bluechi_controller_is_ok: host bluechi-agent is online."
info_message "PASS: check_bluechi_controller_is_ok()"
exit 0
fi
}
check_bluechi_controller_is_ok

View File

@ -3,38 +3,25 @@
# shellcheck disable=SC1091
source ../e2e/lib/utils
print_journal_for_bluechi() {
info_message "Journal for bluechi-controller:\n"
journalctl -r -u bluechi-controller -n 100
info_message "Journal for local bluechi-agent:\n"
journalctl -r -u bluechi-agent -n 100
info_message "Journal for qm bluechi-agent:\n"
journalctl -r -u qm -n 100
}
# Verify bluechi nodes are connected
check_bluechi_is_ok(){
LOCAL=localrootfs
LOCAL_QM=qm.localrootfs
bluechi_controller_status=$(systemctl status bluechi-controller | tail -2)
regex_ASIL_bluechi_agent="Registered managed node from fd [0-9]{1,2} as 'localrootfs'"
regex_QM_bluechi_agent="Registered managed node from fd [0-9]{1,2} as 'qm.localrootfs'"
if ! bluechi-is-online node "${LOCAL}" --wait=5000; then
info_message "FAIL: check_bluechi_is_ok: host bluechi-agent ${LOCAL} is not connected to controller."
print_journal_for_bluechi
if [[ ! "${bluechi_controller_status}" =~ ${regex_ASIL_bluechi_agent} ]]; then
info_message "FAIL: check_bluechi_is_ok: host bluechi-agent is not connected to controller.\n ${bluechi_controller_status}"
exit 1
fi
if ! bluechi-is-online node "${LOCAL_QM}" --wait=5000; then
info_message "FAIL: check_bluechi_is_ok: qm bluechi-agent ${LOCAL_QM} is not connected to controller."
print_journal_for_bluechi
elif [[ ! "${bluechi_controller_status}" =~ ${regex_QM_bluechi_agent} ]]; then
info_message "FAIL: check_bluechi_is_ok: QM bluechi-agent is not connected to controller.\n ${bluechi_controller_status}"
exit 1
else
info_message "check_bluechi_is_ok: host bluechi-agent is connected to controller."
info_message "check_bluechi_is_ok: QM bluechi-agent is connected to controller."
info_message "PASS: check_bluechi_is_ok()"
exit 0
fi
info_message "check_bluechi_is_ok: host bluechi-agent is connected to controller."
info_message "check_bluechi_is_ok: QM bluechi-agent is connected to controller."
info_message "PASS: check_bluechi_is_ok()"
exit 0
}
check_bluechi_is_ok

View File

@ -1 +0,0 @@
output: This is the file to copy

View File

@ -1 +0,0 @@
This is the file to copy

View File

@ -1,7 +0,0 @@
summary: Test plan for QMCTL using TMT
test: ./test_qmctl.sh
duration: 10m
tag: qmctl-test
tier: 0
framework: shell
id: 9b3f962e-758a-473b-b8ea-540a177b9134

View File

@ -1,22 +0,0 @@
#!/bin/bash
# shellcheck disable=SC1091
. ../e2e/lib/utils
QMCTL_SCRIPT="../../tools/qmctl/qmctl"
python3 $QMCTL_SCRIPT cp ./files/file-to-copy.txt qm:/tmp
expected_output_file="./files/file-to-check-cp.txt"
actual_output_temp_file=$(mktemp)
python3 $QMCTL_SCRIPT exec cat /tmp/file-to-copy.txt > "$actual_output_temp_file"
if diff "$actual_output_temp_file" "$expected_output_file" > /dev/null; then
info_message "The output matches the content of '$expected_output_file'."
info_message "PASS: qmctl cp command executed successfully"
exit 0
else
echo "FAIL: The output does NOT match the content of '$expected_output_file'."
exit 1
fi

Some files were not shown because too many files have changed in this diff Show More