I wrote a simple playbook to collect information regarding OS version for all hosts in inventory:
`
- name: “Get OS versions Ansible playbook”
hosts: all
gather_facts: no
tasks:
-
name: “Fetch OS details”
shell: “cat /etc/redhat-release”
register: result -
name: “Print OS details”
debug: msg=“redhat-release = ‘{{ result.stdout }}’”
`
$ ansible-playbook -i inventory get-os-varsions.yml
Unfortunately on few hosts I received bizarre error:
fatal: [host1]: FAILED! => { "changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n File \"/tmp/ansible_uSOBbv/ansible_module_command.py\", line 98, in ?\r\n from ansible.module_utils.basic import AnsibleModule\r\n File \"/tmp/ansible_uSOBbv/ansible_modlib.zip/ansible/module_utils/basic.py\", line 93, in ?\r\nImportError: cannot import name Mapping\r\n", "msg": "MODULE FAILURE", "rc": 1 }
therefore I enabled keeping remote files:
$ export ANSIBLE_KEEP_REMOTE_FILES=1
and executed playbook just for failed host:
$ ansible-playbook -i inventory get-os-varsions.yml --limit host1 -vvvv
Using module_utils file /usr/lib/python2.7/site-packages/ansible/module_utils/basic.py Using module_utils file /usr/lib/python2.7/site-packages/ansible/module_utils/six/__init__.py Using module_utils file /usr/lib/python2.7/site-packages/ansible/module_utils/_text.py Using module_utils file /usr/lib/python2.7/site-packages/ansible/module_utils/pycompat24.py Using module_utils file /usr/lib/python2.7/site-packages/ansible/module_utils/six/_six.py Using module file /usr/lib/python2.7/site-packages/ansible/modules/commands/command.py <plabb59.sgdcelab.sabre.com> ESTABLISH CONNECTION FOR USER: funcusr on PORT 22 TO plabb59.sgdcelab.sabre.com <plabb59.sgdcelab.sabre.com> EXEC /bin/sh -c '( umask 77 && mkdir -p "
echo /tmp/ansible-tmp-1500044507.29-45810672852156 " && echo ansible-tmp-1500044507.29-45810672852156="
echo /tmp/ansible-tmp-1500044507.29-45810672852156 " ) && sleep 0' <plabb59.sgdcelab.sabre.com> PUT /tmp/tmpv_ifKv TO /tmp/ansible-tmp-1500044507.29-45810672852156/command.py <plabb59.sgdcelab.sabre.com> EXEC /bin/sh -c 'chmod u+x /tmp/ansible-tmp-1500044507.29-45810672852156/ /tmp/ansible-tmp-1500044507.29-45810672852156/command.py && sleep 0' <plabb59.sgdcelab.sabre.com> EXEC /bin/sh -c '/usr/bin/python /tmp/ansible-tmp-1500044507.29-45810672852156/command.py && sleep 0'
ssh into failed host, went to /tmp/ansible-tmp-… and executed command by hand:
$ /usr/bin/python /tmp/ansible-tmp-1500044507.29-45810672852156/command.py
result was the same:
Traceback (most recent call last): File "/tmp/ansible_TLPERw/ansible_module_command.py", line 98, in ? from ansible.module_utils.basic import AnsibleModule File "/tmp/ansible_TLPERw/ansible_modlib.zip/ansible/module_utils/basic.py", line 93, in ? ImportError: cannot import name Mapping
I started to think was is going on? I noticed that on controller host python2.7 is used, but on remote host there is:
$ ll /usr/bin/python*
/usr/bin/python (python2.4)
/usr/bin/python2 → python
/usr/bin/python2.4
/usr/bin/python26
/usr/bin/python2.6
/usr/bin/python2.6-config
therefore I altered a little bit an environment:
cd /usr/bin/
mv python python.bak
ln -s python2.6 python
Then I returned to /tmp/ansible-tmp-… and executed
$ /usr/bin/python /tmp/ansible-tmp-1500044507.29-45810672852156/command.py
result was successful:
{"changed": true, "end": "2017-07-14 10:19:09.499954", "stdout": "Red Hat Enterprise Linux Server release 5.11 (Tikanga)", "cmd": "cat /etc/redhat-release", "rc": 0, "start": "2017-07-14 10:19:09.492287", "stderr": "", "delta": "0:00:00.007667", "invocation": {"module_args": {"warn": true, "executable": null, "_uses_shell": true, "_raw_params": "cat /etc/redhat-release", "removes": null, "creates": null, "chdir": null}}}
Just for curiosity I opened command.py and I noticed huge chunk of base64 encoded something called ZIPDATA.
Since I could not find AnsibleModule inside command.py (it was in traceback), therefore it must be hidden
inside this big chunk of something. I guess the clue of problem is that pythion2.7 prepares this chunk of something
but python2.4 cannot understand this something and bails out with nasty traceback which is unreadable to regular Ansible user.
Does anyone know how to avoid such a problem on environments which different OS versions (and thus Python interpreters)?