Ansible - Firewalld Module on Ubuntu

Getting Ansible firewalld tasks working on Ubuntu based systems

Posted by Michael Wadman on November 17, 2018

Overview

When trying to run an Ansible “firewalld” task on an Ubuntu machine recently, I received the following error:

TASK [Firewalld Task] **************************
fatal: [vagrant-test]: FAILED! => {"changed": false, "msg": "Python Module not found: firewalld and its python module are required for this module, version 0.2.11 or newer required (0.3.9 or newer for offline operations)"}

Here is the task that I’m running:

name: Firewalld Test Task
firewalld:
  service: https
  state: enabled

Investigation

After a quick google search, I found some other people have run into this as well.
Although there were some fixes noted in the above issues, none of them sat well with me as they required installing extra packages.

There has to be a better way right?

Hunting further took me back to the Ansible firewalld module documentation, which includes the following notes:

Not tested on any Debian based system.

Requires the python2 bindings of firewalld, which may not be installed by default.

For distributions where the python2 firewalld bindings are unavailable (e.g Fedora 28 and later) you will have to set the ansible_python_interpreter for these hosts to the python3 interpreter path and install the python3 bindings.

Those last points ring true with us. But how do we go about fixing this?

Rectification

Well, turns out that the fix is considerably easier than installing extra packages.

Following the advice from that last note in the documentation, we first need to check what version of the bindings we’re using:

$ apt-cache depends firewalld | grep Depends | grep python
  Depends: python3-dbus
  Depends: python3-gi
  Depends: python3-slip-dbus
  Depends: <python3:any>

Now that we’ve confirmed we’re using the python3 bindings, we’ll simply tell Ansible to use python3 when running the task.
This is accomplished by setting the variable ansible_python_interpreter to “/usr/bin/python3”.

In true Ansible fashion, the variable can be set in multiple ways/places. But because I don’t want it to impact the running of my other tasks, I’m going to use the task level vars option, as below:

name: Firewalld Test Task
firewalld:
  service: https
  state: enabled
vars:
  ansible_python_interpreter: '/usr/bin/python3'

This results in a happy firewalld task and a change of the firewalld state on the host:

TASK [Firewalld Task] **************************
changed: [vagrant-test]

Conclusion

This was another quick post, which may help other people who are running into a similar issue.

I could have gone into more detail around how I might refactor this task to include logic so that the python interpreter is only changed when running against Ubuntu machines, but I wanted to keep this quick and easy to read.

Appendices

References

Ansible Github Issue #24855
Ansible Modules Extras Github Issue #1282

Versions used

Local Machine:

  • Operating System: Kubuntu-18.04.1
  • Ansible: 2.7.2

Remote Machine:

  • Operating System: Ubuntu-16.04.5
  • Firewalld: 0.4.0