[Ansible] Solution for "(libselinux-python) aren't installed!" for CentOS 6 Playbook

table of contents
Hello everyone.
I'm Naka from the Systems Solutions Department, and I occasionally get cravings for tsukemen (dipping noodles) and pasta.
When attempting to update or modify a manually managed CentOS 6 environment using Ansible, the error "(libselinux-python) aren't installed!"is frequently encountered.
This error is likely to be fixed manually
However,when you have a large number of machines and want to manage them with Ansible, but before that, you have to deal with each one manuallyita hassle.
So I thought, "Wouldn't it be easier if we could solve that with Ansible?"and wrote a Playbook.
This time, we will introduce and explain the "Playbook for resolving '(libselinux-python) aren't installed!' for CentOS 6."
Introduction
- We do not recommend using CentOS 6. This is merely a
for situations where you are forced to use CentOS 6temporary workaround. - is an unsupported version.
Thisintended as a temporary workaroundandis not recommended.
Basic causes
(libselinux-python) isn't installed!
When using modules that change, such as file operations,
- not completely disabled.is
- Furthermore(*1) the libselinux-python package is not installed(*2)
This is the error that occurs when
*1. This error will not occur if SELinux is disabled.
*2. Ansible runs on Python, so Python needs to be able to interact with SELinux.
* For Python 3, this would be "python3-libselinux," but it does not seem to be generally provided for CentOS 6.
Manual Solution
# sudo yum install libselinux-python
This problem will basically be resolved if you install "libselinux-python" on the target side
* For Python 3, use "python3-libselinux"
However, CentOS 6 is end-of-life (EOL), if the repositories are left at their default settings a high probability that yum won't work.
In that case you will need to do a local install using wget & rpm from an available repository
Therefore, manual response across multiple environments is quite difficult
Q. Why change it in a playbook?
A. It's not just that it's troublesome to do manual work beforehand when you want to use Ansible;
it's easy to think, "If manual work is necessary, I might as well do everything manually,"which defeats the purpose.Therefore,to "actively shift towards using Ansible for anything that can be reliably done with it."our stance is
Q. Will it not be compatible with CentOS 7?
A. I think it would be smarter to handle version differences by separating the Playbooks and making judgments/branching at the include/import stage
I was wondering whether to make it compatible, but it already includes a branch for when "yum" cannot be used, which makes it a bit complicated
The repository directory hierarchy names may change depending on the OS version, which will further increase the number of branches
We decided not to include version branching within a single Playbook because we felt it would reduce readability and maintainability
Execution environment
■ Linux environment
OS: AlmaLinux release 8.5 (WSL2 environment)
Shell: Bash
Docker: 26.1.0, build 9714adc■ Ansible Environment (Docker container within WSL2)
OS: AlmaLinux release 8.9
Ansible: Ansible-core 2.12.10■ Windows Environment
OS: Windows 11 Pro (Version: 23H2)
Language setting: Changed to Japanese■ CentOS 6 environment (Vagrant + VirtualBox)
OS: CentOS 6.9 (bento / centos-6.9)
Vagrant: 2.4.1
VirtualBox: 7.0.18 r162988 (Qt5.15.2)
IP: 192.168.33.15
Ansible 2.12 environment construction procedure
, compatibleversion of Ansible (2.12)we will use
In the previous article, we explained how to build Ansible 2.12, so please refer to this
[Ansible 2.12] Build an Ansible execution environment for CentOS 6 using Docker in WSL2
Playbook
when running a Playbook on a CentOS 6 environment,including/importing certain components at the very beginning will prevent errors.thatto be used proactivelyis designed
*Of course, it is also possible to resolve the issue by using this Playbook after the error has occurred
libselinux-python_wget.yml
This Playbook is loaded using `import_tasks` in `main.yml`.
(This is because I prefer to separate Playbooks by role to improve reusability, readability, and maintainability.)
--- ## Variable default # wget_repo | default ("http://ftp.iij.ad.jp/pub/linux/centos-vault") - name: Check SELinux ansible.builtin.command: cmd: getenforce register: SELinux_result - ansible.builtin.debug: var: SELinux_result.stdout - name: Check libeselinux-python ansible.builtin.shell: cmd: rpm -aq | grep libselinux-python register: rpm_result ignore_errors: yes - ansible.builtin.debug: var: rpm_result.stdout # If SELinux is disabled, Ansible can be run without any additions, so it will not be executed. # Also, if libselinux-python is already installed, it will not be executed. - name: yum install libselinux-python ansible.builtin.yum: name: libselinux-python state: present register: yum_libselinux_result ignore_errors: yes when: not ( SELinux_result.stdout is search("disabled") ) and not ( rpm_result.stdout is search("libselinux-python*")) # If installation with yum fails, install with wget - name: Setup libselinux-python when: yum_libselinux_result is failed and not ( rpm_result.stdout is search("libselinux-python*")) block: # Since the package name changes depending on the version, store the HTML of the package list in a variable -name: Get OS_version Packages ansible.builtin.uri: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/" method: GET return_content: yes register: packages_content # Get the rpm name of "libselinux-python" from HTML - name: Extract rpm_name ansible.builtin.set_fact: rpm_name: "{{ packages_content.content | regex_search('libselinux-python-(.*?)\\.x86_64\\.rpm') }}" - ansible.builtin.debug: var: rpm_name # Download with the obtained rpm name - name: Download libselinux-python ansible.builtin.get_url: url: "{{ wget_repo | default('http://ftp.iij.ad.jp/pub/linux/centos-vault') }}/{{ ansible_distribution_version }}/os/x86_64/Packages/{{ rpm_name }}" dest: "/tmp/{{ rpm_name }}" # Install with rpm for situations where yum cannot be used - name: Install libselinux-python ansible.builtin.command: rpm -ivh /tmp/"{{ rpm_name }}"
I've written most of my intentions in the comments, but I'll explain them below
# wget_repo: | default ("http://ftp.iij.ad.jp/pub/linux/centos-vault")
If you cannot use yum, get libselinux-python directly from the repository:
The repository to be used is specified using a variable, but if no variable is specified, a comment is added at the beginning to clearly state that the repository used is from IIJ
- name:Check SELinux
- name:Check libeselinux-python
In environments where SELinux is disabled, it runs without "libselinux-python," so it's unnecessary.
First, the status is checked and then stored in a variable for determination.
Furthermore,considering that CentOS 6 may not support yum, we will check if it has been installed using rpm via the Shell module.
This result is also saved to a variable for verification.
- name: yum install libselinux-python
the SELinux status isother than "disabled"and"libselinux-python" is not installedThis command is executed only
Try installing it using the yum module, and if it says Installed or Already Installed, then it's OK
If "yum" fails to work, the process continues with "ignore_errors: yes,"but the failure of the task is recorded in a variable for checking, and subsequent tasks attempt to retrieve the data directly from the repository.
- name:Setup libselinux-python
when:yum_libselinux_result is failed
block:
when installation via "yum" fails(when condition).
It retrieves packages directly from the repository andinstalls them using rpm.
First, use the "ansible_distribution_version" from ansible_facts to get the official package name of "libselinux-python" from the directory hierarchy of the repository that matches the minor version of the OS and save it as a variable
Then use that variable to download it using the get_uri module and install it locally using rpm via the command module
Example
Inventory file for verification environment
While CentOS 6 (bento / centos-6.9) defaulted to password authentication, environments with password authentication (which is not recommended) can still exist, so we conducted the test in this state.
-- all: vars: ansible_user: vagrant hosts: targetnode: ansible_host: 192.168.33.15 ansible_ssh_pass: vagrant
main.yml
Instead of writing tasks in main.yml, I've adopted a style where I import Playbooks using import_tasks.
(This is because I prefer to separate Playbooks by role to improve reusability, readability, and maintainability.)
- name: libselinux-python hosts: targetnode< become: yes vars: wget_repo: "http://ftp.iij.ad.jp/pub/linux/centos-vault" tasks - name: Include libeselinux-python(wget) ansible.builtin.import_tasks: libselinux-python_wget.yml
Playbook execution
In this article, we will run it from a container with an older Ansible version
[root@author's container environment work]# ansible-playbook -i hosts main.yml
lastly
It was time-consuming, but I tried to automate some standardized tasks using Ansible.
This means I can reuse it many times, and it was a good learning experience in terms of becoming more familiar with Ansible.
Since CentOS 6 environments often lack the ability to use "yum," making Ansible implementation a high hurdle,
I hope this article will provide readers with a starting point for exploring Ansible and offer some useful knowledge and information.
Thank you for reading this far!
Reference materials
ansible.builtin.yum module – Manages packages with the yum package manager
https://docs.ansible.com/ansible/9/collections/ansible/builtin/yum_module.html
4
