RHEL System Roles playbooks fail when run on localhost

Solution Verified - Updated

Environment

  • RHEL 8.6 or later with Ansible Core

Issue

  • When running a playbook utilizing the implicit localhost that calls a RHEL System Role on RHEL 8.6 or later with Ansible Core, the playbook fails with messages similar to:

Example 1:

TASK [rhel-system-roles.storage : get required packages] *****************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NameError: name 'devices' is not defined
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/root/.ansible/tmp/ansible-tmp-1641592123.0730848-36587-242370360571615/AnsiballZ_blivet.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/root/.ansible/tmp/ansible-tmp-1641592123.0730848-36587-242370360571615/AnsiballZ_blivet.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/root/.ansible/tmp/ansible-tmp-1641592123.0730848-36587-242370360571615/AnsiballZ_blivet.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible.modules.blivet', init_globals=dict(_module_fqn='ansible.modules.blivet', _modlib_path=modlib_path),\n  File \"/usr/lib64/python3.8/runpy.py\", line 207, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.8/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib64/python3.8/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_blivet_payload_f62asr5l/ansible_blivet_payload.zip/ansible/modules/blivet.py\", line 577, in <module>\n  File \"/tmp/ansible_blivet_payload_f62asr5l/ansible_blivet_payload.zip/ansible/modules/blivet.py\", line 578, in BlivetDiskVolume\nNameError: name 'devices' is not defined\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Example 2 (Note: The warning about the loop variable 'item' below is not related to this issue):

TASK [redhat.rhel_system_roles.selinux : Set SELinux booleans] *****************************************************************************
[WARNING]: TASK: redhat.rhel_system_roles.selinux : Set SELinux booleans: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and unexpected behavior.
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'selinux'
failed: [localhost] (item={'name': 'selinuxuser_execmod', 'state': 'on'}) => {"ansible_loop_var": "item", "changed": false, "item": {"name": "selinuxuser_execmod", "state": "on"}, "msg": "Failed to import the required Python library (libselinux-python) on host01's Python /usr/bin/python3.11. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"}

Resolution

Choose one of the options below to workaround the issue:

  • Create an inventory file that lists localhost with the ansible_connection=local option.

    • For example, an inventory file with:
      • localhost ansible_connection=local
    • Run ansible-playbook and specify that this inventory file should be used:
      • ansible-playbook -i inventory <playbook>
  • Create an inventory file that lists localhost.

    • Note that this will result in ansible-playbook connecting to the localhost over SSH with SSH key authentication, which must have previously been configured.
    • For example, an inventory file with:
      • localhost
    • Run ansible-playbook and specify that this inventory file should be used:
      • ansible-playbook -i inventory <playbook>
  • Use implicit localhost, with the ansible_python_interpreter variable set to use platform-python

    • For example:
      • ansible-playbook <playbook> -e 'ansible_python_interpreter=/usr/libexec/platform-python'

Root Cause

  • RHEL 8.6 uses Ansible Core 2.12 to support RHEL System Roles. Ansible Core 2.12 utilizes Python 3.8 which does not contain all of the required Python modules (for example the blivet module for the storage RHEL System Role).

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.