Chasing Ansible 2.9 Paramiko Error on Exit

needle-in-a-haystack-1752846_1920

As a heavy user of Ansible, I am always concerned about updating to the latest version in order to have the most-recent security features and patches. With a user base of over 500, pushing updates to everyone almost always causes someone to trip. We recently updated to Ansible 2.9.0. A few users started seeing unusual python exceptions related to one of the packages Ansible depends on: Paramiko. For example:

ansible --version
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line 120, in _join_lingering_threads
    for thr in _active_threads:
TypeError: 'NoneType' object is not iterable
Error in sys.exitfunc:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line 120, in _join_lingering_threads
    for thr in _active_threads:
TypeError: 'NoneType' object is not iterable

I used a *very* unscientific method to get this user up and running. I have a testbed in my lab that is working great with Ansible 2.9. I used the command `pip show` to walk through the dependencies of Ansible. Once I compiled a list of the versions of the dependencies 2 levels down, I compared them with the user’s machine. There were a few differences. When we used pip to manually modify the installed versions on this user’s machine, everything started working properly.

I offer the following list for what worked for us on CentOS 7 and Ansible 2.9. Your mileage may vary:

ansible==2.9
ipaddr==2.2.0
netaddr==0.7.19
netmiko==2.3.0
paramiko==2.6.0
cryptography==2.8
pynacl==1.3.0
bcrypt==3.1.7
cffi==1.13.1
six==1.9.0
enum34==1.1.6
requests==2.23.0

The main take-away from this post is *not* the needle-in-a-haystack magic combination shown, above. The main point is that package management in Python can be tricky. The version of pip you are using, the version of Python you have installed, and a dozen other factors can come into play. `pip show` is one tool you can use to dissect the problem to do some trial and error – especially when the Internet seems to be silent about the needle you are seeking.