On EL8-based distributions (RHEL, AlmaLinux, Rocky), Ansible is effectively capped at version 2.16. This is because Ansible 2.17+ requires a controller/target Python version ≥ 3.7. While EL8 provides Python 3.12, it does not provide the necessary C-extensions (bindings) for dnf or rpm for any version other than the system-locked Python 3.6.
To use Ansible 2.17+, administrators currently have to split their
inventory or manually toggle ansible_python_interpreter, creating
significant technical debt.
Reference: https://forum.ansible.com/t/python-3-7-impact-on-el8-future-for-el9/6229/12
The goal of this project is to provide relocatable install/site-packages/
contents, containing the Python 3.12 equivalents of
python3-gpgpython3-libcompspython3-libdnfpython3-hawkey
The contents of the folder can be copied to an Ansible Python 3.12 virtual environment.
For these to be usable by Ansible for system tasks you would still
need python3-dnf and python3.12-rpm packages which can be obtained from the platform.
When the Ansible controller runs a DNF task on an EL8 target using a
modern Python (like 3.12), the module first attempts a native import dnf.
If this fails, Ansible attempts to "respawn" the module by calling
/usr/libexec/platform-python (Python 3.6).
Because Ansible 2.17+ dropped support for Python 3.6, this respawn fails. Consequently, DNF/RPM tasks are restricted to the legacy Ansible 2.16/Community 9.x ecosystem.
This repository provides the "missing link": build scripts to compile the "Big 4" C-extensions specifically for Python 3.12 on EL8. This enables Ansible 2.17+ to manage EL8 nodes natively without respawning or falling back to legacy interpreters.
- libdnf (python3-libdnf): The core C logic for DNF.
- hawkey (python3-hawkey): The high-level API for query resolution.
- gpgme (python3-gpg): GPG signing and verification.
- libcomps (python3-libcomps): Handling of package groups and comps metadata.
The python3-dnf package itself is pure Python and can be reused
verbatim. In practice, this can be achieved by copying the
/usr/lib/python3.6/site-packages/dnf
folder into the target environment.
python3.12-rpm is provided by the platform - it can be reused
for the target environment by copying /usr/lib64/python3.12/site-packages/rpm
or using ... --system-site-packages ... when creating the target
environment.
While a Python 3.12 equivalent of python3-libselinux might seem like a
prerequisite, it is not a "hard" dependency for Ansible.
If a native import selinux fails, the Ansible
engine is designed to fallback to CLI-based mechanisms.
Thus, the "Big 4" focus remains on the DNF/RPM stack where no such CLI fallback exists for complex library interactions.
RPATH-Free Binaries: The build process is intentionally configured to
avoid hardcoding RPATH or RUNPATH. These extensions are designed
to bind directly to the EL 8 system libraries in /usr/lib64 (e.g., libdnf.so.2),
Deployment: The contents of install/site-packages/ are relocatable. You
can rsync them into a host-specific virtual environment or—at your
own risk (AYOR)—into the global system site-packages at
/usr/lib64/python3.12/site-packages.
SWIG 3/4: both the default SWIG 3 and modular SWIG 4.1 have been tested to work.
At this stage, we are providing reproducible build scripts rather than pre-compiled RPMs. We want to ensure the build process is robust across various EL8 minor versions (8.6 through 8.10) and collect user feedback on edge-case DNF behaviors before moving to a formal release.
Source Parity: These scripts leverage official platform Source RPMs (.src.rpm) to ensure the resulting bindings are 1:1 functional matches with the system versions.
Builds: The scripts may perform partial/full autotools or cmake runs to generate headers.
Root Access Required: Because the build process must satisfy
build-time dependencies (e.g., zchunk-devel, expat-devel,
libsolv-devel), you must have root or sudo privileges on the build
host to install the necessary development headers and .so links
before starting the build.
This project does not attempt to:
- replace or modify the system DNF stack
- provide alternative dependency resolution logic
- backport newer DNF features from EL9