Ansible is using wrong version of Python - python

I have been dealing with this issue for a couple of days now. I am running ansible on a raspberry pi. I have made Python3.7 the default version of Python. Apparently Ansible wants to use Python 2.7. I have added Version 3.7 in the vars in the playbook but this does not change the module location. It still looks for the modules in Python 2.7.
I am not sure how to tell Ansible to use 3.7 for all the modules and the interpreter.
pi#pi:~ $ python --version
Python 3.7.2
pi#pi:~ $ ansible-playbook vm.yaml -vv
ansible-playbook 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/pi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
Using /etc/ansible/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAYBOOK: vm.yaml *************************************************************************************************************************************
1 plays in vm.yaml
PLAY [localhost] **********************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************
task path: /home/pi/vm.yaml:12
ok: [localhost]
META: ran handlers
TASK [Gather info about the vmware guest vm] ******************************************************************************************************************
task path: /home/pi/vm.yaml:28
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'pyVim'
fatal: [localhost -> localhost]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (PyVmomi) on pi's Python /usr/bin/python3. Please read module documentation and install 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"}
PLAY RECAP ****************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
pi#pi:~ $

To let ansible use the python version other than what it is taking by default, you can use ansible.cfg file inside the project root from where you are running ansible-playbook command.
This file is like a configuration file from which ansible picks up details when it executes a playbook.
Once of its configuration option is interpreter_python where you specify the executable path.
Let's do this step by step :
First find the executable path of the python version you would like ansible to use. e.g. if it is python 3.10, you would run which python3.10 from your terminal. It will give you something like /usr/local/bin/python3.10 in the output(which may change if you have it installed in a different directory).
Create a file called ansible.cfg in the project root from where you are running your playbooks and add following :
[defaults]
stdout_callback = debug
interpreter_python= /usr/local/bin/python3.10
Now when you run the playbooks from this directory, ansible will take the interpreter_python configuration and use python3.10
An important note that now if you run ansible-playbook --version it might still show you the older python version it was using. But when you execute the playbook, it will take the ansible.clf file into account.

Q: "How to tell Ansible to use 3.7"
A: It's not possible to select the version of Python the ansible* utilities are running on. This version of Python depends on how the Ansible utilities(package) were built. This is the python version the utilities will display
shell> ansible --version
ansible [core 2.14.1]
config file = /export/scratch/tmp7/test-206/ansible.cfg
configured module search path = ['/home/admin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/admin/.local/lib/python3.9/site-packages/ansible
ansible collection location = /home/admin/.local/lib/python3.9/site-packages
executable location = /home/admin/.local/bin/ansible
python version = 3.9.16 (main, Dec 7 2022, 01:11:51) [GCC 9.4.0] (/usr/bin/python3.9)
jinja version = 3.1.2
libyaml = True
The utilities below will display the same
shell> ansible-playbook --version
shell> ansible-inventory --version
...
There may be more versions of Python installed both on the controller and on the remote hosts. It's a complex process of how Ansible selects which version of Python will be used to execute the modules on a remote host. See:
Interpreter Discovery: "Unless configured otherwise, Ansible will attempt to discover a suitable Python interpreter on each target host."
INTERPRETER_PYTHON: "Configuration options how to select Python on the remote hosts."
Debugging modules to learn details on how the Ansible modules are executed on a remote host.
Setting the Python interpreter in BSD
It's necessary to understand that Ansible can manage both remote hosts and localhost. For example, on the controller (localhost), this ansible utility uses python version = 3.9.16. The version of Python to execute the modules may be different.
shell> ls -1 /usr/bin | egrep '^python[2,3]\.[0-9]$'
python2.7
python3.8
python3.9
By default, Ansible 'discovered' /usr/bin/python3 in Ubuntu which is a link to python3.8
shell> ansible localhost -m setup | grep -i python
"ansible_python": {
"executable": "/usr/bin/python3",
"type": "cpython",
"ansible_python_version": "3.8.5",
"ansible_selinux_python_present": true,
"discovered_interpreter_python": "/usr/bin/python3",
shell> ll /usr/bin/python3
lrwxrwxrwx 1 root root 9 Apr 27 2020 /usr/bin/python3 -> python3.8*
You can configure INTERPRETER_PYTHON in many different ways:
a) In the variable ansible_python_interpreter on the command line
shell> ansible localhost -m setup -e ansible_python_interpreter=/usr/bin/python3.9 | grep -i python
"ansible_python": {
"executable": "/usr/bin/python3.9",
"type": "cpython",
"ansible_python_version": "3.9.16",
"ansible_selinux_python_present": true,
, but you can declare the variable in other precedence and in various scopes. See Variable precedence: Where should I put a variable?. You can even configure different versions for single tasks. For example,
- hosts: localhost
tasks:
- command: "echo {{ ansible_python_interpreter }}"
register: out
vars:
ansible_python_interpreter: /usr/bin/python3.8
- debug:
var: out.stdout
- command: "echo {{ ansible_python_interpreter }}"
register: out
vars:
ansible_python_interpreter: /usr/bin/python3.9
- debug:
var: out.stdout
gives (abridged)
TASK [command] ***********************************************************************************************************************
changed: [localhost]
TASK [debug] *************************************************************************************************************************
ok: [localhost] =>
out.stdout: /usr/bin/python3.8
TASK [command] ***********************************************************************************************************************
changed: [localhost]
TASK [debug] *************************************************************************************************************************
ok: [localhost] =>
out.stdout: /usr/bin/python3.9
b) In the environment variable ANSIBLE_PYTHON_INTERPRETER on the command line
shell> ANSIBLE_PYTHON_INTERPRETER=/usr/bin/python3.9 ansible localhost -m setup | grep -i python
"ansible_python": {
"executable": "/usr/bin/python3.9",
"type": "cpython",
"ansible_python_version": "3.9.16",
"ansible_selinux_python_present": true,
c) In the configuration
shell> grep -B 1 interpreter_python ansible.cfg
[defaults]
interpreter_python = /usr/bin/python3.9
shell> ansible localhost -m setup | grep -i python
"ansible_python": {
"executable": "/usr/bin/python3.9",
"type": "cpython",
"ansible_python_version": "3.9.16",
"ansible_selinux_python_present": true,
d) In the inventory for a single host
shell> cat hosts
localhost ansible_python_interpreter=/usr/bin/python3.9
shell> ansible localhost -m setup | grep -i python
"ansible_python": {
"executable": "/usr/bin/python3.9",
"type": "cpython",
"ansible_python_version": "3.9.16",
"ansible_selinux_python_present": true,
e) In the inventory for a group of hosts
shell> cat hosts
[test]
test_11
test_12
test_13
[test:vars]
ansible_user=admin
ansible_python_interpreter=/usr/local/bin/python3.8
shell> ansible test_11 -m setup | grep -i python
"ansible_python": {
"executable": "/usr/local/bin/python3.8",
"type": "cpython",
"ansible_python_version": "3.8.12",
"status": "Missing selinux Python library"
"ansible_selinux_python_present": false,

You probably need to change this.
ansible-playbook 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/pi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible-playbook
python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
python version is defined as 2.7.16, which you need to change.

Related

Ansible - Unhandled error in Python interpreter discovery for

I have a problem trying to ping to machines using ansible, 1 is fedora 35 the 2nd is ubuntu 21.
when I run
ansible all -i inventory -m ping -u salam -k
I get the following warnings
[WARNING]: Unhandled error in Python interpreter discovery for host
myubuntuIP: unexpected output from Python interpreter discovery
[WARNING]: sftp transfer mechanism failed on [myubuntuIP]. Use
ANSIBLE_DEBUG=1 to see detailed information
[WARNING]: scp transfer
mechanism failed on [myubuntuIP]. Use ANSIBLE_DEBUG=1 to see detailed
information myubuntuIP | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong" }
[WARNING]: Platform unknown on host myfedoraIP is using the discovered Python interpreter at /usr/bin/python, but future
installation of another Python interpreter could change the meaning of
that path. See
https://docs.ansible.com/ansible-core/2.14/reference_appendices/interpreter_discovery.html
for more information. myfedoraIP | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
when I do
which python3
on both machines, I get 2 different paths as follows
/usr/bin/python3 for fedora box /bin/python3 for ubuntu box
I understand from 1 thread here that we should indicate the path of python in ansible.cfg file, Can I indicate 2 different paths in the ansible.cfg? If yes how? and why ansible is not able to find the python path?
First, the error on your Ubuntu system appears unrelated to this question; it says:
[WARNING]: sftp transfer mechanism failed on [myubuntuIP]
[WARNING]: scp transfer mechanism failed on [myubuntuIP]
I suspect to diagnose that issue you'll need to follow the instructions in the error message, set ANSIBLE_DEBUG=1, and if the cause isn't immediately obvious open a new question here for that particular issue.
I understand from 1 thread here that we should indicate the path of python in ansible.cfg file, Can I indicate 2 different paths in the ansible.cfg? If yes how?
You don't set this in your ansible.cfg (unless you really do want a single setting for all your hosts); you set this in your Ansible inventory or in your host_vars or group_vars directory. For example, to set this on a specific host in your inventory, you might do something like this:
all:
hosts:
host1:
ansible_python_interpreter: /usr/bin/python3
host2:
host3:
You could accomplish the same thing by placing:
ansible_python_interpreter: /usr/bin/python3
In host_vars/host1.yaml.
If the same configuration applies to more than one host, you can group them and then apply the setting as a group variable. For example, to apply the setting only to a subset of your hosts:
all:
hosts:
host1:
children:
fedora_hosts:
vars:
ansible_python_interpreter: /usr/bin/python3
hosts:
host2:
host3:
Or to apply it globally:
all:
vars:
ansible_python_interpreter: /usr/bin/python3
hosts:
host1:
host2:
host3:
And why ansible is not able to find the python path?
That's not what the warning is telling you -- it was able to find the Python path (/usr/bin/python), but "future installation of another Python interpreter could change the meaning of that path" (because /usr/bin/python, depending on your distribution, could actually be python 2 instead of python 3, etc).

Python error running Ansible via SSM against EC2

I'm trying to run a fairly routing ansible playbook against ec2 instances in my AWS environment
---
- name: get python
hosts: myhost
become: true
vars:
ansible_connection: aws_ssm
ansible_aws_ssm_profile: myprofile
ansible_aws_ssm_region: eu-west-1
ansible_aws_ssm_bucket_name: "mybucketname"
tasks:
- name: run command
command: pwd
I can see that the connection to the instance works, but I get the following error
fatal: [i-000011112222aaaa]: FAILED! => {
"ansible_facts": {},
"changed": false,
"failed_modules": {
"ansible.legacy.setup": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3.6"
},
"failed": true,
"module_stderr": "",
"module_stdout": " File \"/home/ssm-user/.ansible/tmp/ansible-tmp-1641395807.063974-83634-44643497283265/AnsiballZ_setup.py\", line 1\r\r\n <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\r\n ^\r\r\nSyntaxError: invalid syntax\r\r",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1,
"warnings": [
"Platform linux on host i-000011112222aaaa is using the discovered Python interpreter at /usr/bin/python3.6, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible-core/2.11/reference_appendices/interpreter_discovery.html for more information."
]
}
},
"msg": "The following modules failed to execute: ansible.legacy.setup\n"
}
My ansible.cfg looks like this
[defaults]
enable_plugins = aws_ec2
host_key_checking = False
pipelining = True
ansible_python_interpreter = /usr/bin/python3.9
My ansible --version
ansible [core 2.11.6]
config file = /Users/myuser/Repositories/myrepo/ansible/ansible.cfg
configured module search path = ['/Users/myuser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/ansible
ansible collection location = /Users/myuser/.ansible/collections:/usr/share/ansible/collections
executable location = /Library/Frameworks/Python.framework/Versions/3.10/bin/ansible
python version = 3.10.0 (v3.10.0:b494f5935c, Oct 4 2021, 14:59:19) [Clang 12.0.5 (clang-1205.0.22.11)]
jinja version = 3.0.2
libyaml = True
I can see in the ansible --version that python3.10 is being referenced, but I'm specifying 3.9 in my ansible_python_interpreter. Is there a reason on the host side this wouldn't work? Running the command directly on the host works without issue.

ansible commands run only with absolute path

On Ubuntu 20.04.2 LTS there is ansible engine installed with pip3 command:
mariusz#g3:~$ pip3 show ansible
Name: ansible
Version: 4.1.0
However running ansible commands ends with below error:
mariusz#g3:~$ ansible
python3: can't open file '/usr/bin/ansible': [Errno 2] No such file or directory
The PATH variable is set correctly:
mariusz#g3:~$ which ansible
/home/mariusz/.local/bin/ansible
And I can run ansible command with absolute path:
mariusz#g3:~$ /home/mariusz/.local/bin/ansible --version
ansible [core 2.11.1]
config file = /home/mariusz/.ansible.cfg
configured module search path = ['/home/mariusz/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/mariusz/.local/lib/python3.8/site-packages/ansible
ansible collection location = /home/mariusz/.ansible/collections:/usr/share/ansible/collections
executable location = /home/mariusz/.local/bin/ansible
python version = 3.8.5 (default, May 27 2021, 13:30:53) [GCC 9.3.0]
jinja version = 2.11.3
libyaml = True
Any ideas how to solve it without root privileges i.e. creating /usr/bin/ansible symlink?
The entries in the $PATH variable are tried in order, and thus you'd want to relocate your $HOME/.local/bin to the beginning of the list in order for it to win out over the /usr/bin entry that's there now
You can do this in an interactive shell to confirm or deny the theory, and then put at the end of your ~/.bashrc to make it permanent
PATH=$HOME/.local/bin:$PATH
It seems that ansible package, which was installed before, left bash aliases file that was not removed during package uninstall.
$ cat ~/.bash_aliases
alias ansible='python3 /usr/bin/ansible'
alias ansible-doc='python3 /usr/bin/ansible-doc'
alias ansible-galaxy='python3 /usr/bin/ansible-galaxy'
alias ansible-inventory='python3 /usr/bin/ansible-inventory'
alias ansible-playbook='python3 /usr/bin/ansible-playbook'
alias ansible-vault='python3 /usr/bin/ansible-vault'

Ansible Tower - aws_s3 module - set python interpreter and install dependencies

I am trying to deploy the below task via Ansible AWX (Tower) and having some issues with the aws_s3 module.
---
- hosts: all
become: yes
tasks:
- name: Setting host facts for Python interpreter
set_fact:
ansible_python_interpreter: "/usr/bin/python3"
- name: 01 - Download file locally
aws_s3:
bucket: temp-buck-0001
object: /test/quiz.sh
dest: /tmp/quiz.sh
mode: get
- name: 02 - Change the file permissions of the shell scrip to allow for execute
file:
path: /tmp/quiz.sh
mode: "u=x"
- name: 03 - Change the working directory to tmp before executing the command.
shell: quiz.sh >> quizlog.txt
args:
chdir: /tmp
I'm getting the below error when trying to deploy the above ansible play. It seems to have a problem with Python dependencies in particular boto3 and botocore so I attempted to install these manually for testing purposes.
However, I'm receiving the below errors. It concerns dependencies for the aws_s3 module. I'm not sure if I have set up my Python interpreter correctly. Any help would be much appreciated.
Also, if anybody could suggest how to write a task to install Python3x and dependencies which is required for the aws_s3 module that would also be much appreciated.
TASK [01 - Download Metricbeats file locally]
********************************** fatal: [Dev-02]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 20.10.12.114
closed.\r\n", "module_stdout": "/bin/sh: /usr/bin/python3: No such
file or directory\r\n", "msg": "The module failed to execute
correctly, you probably need to set the interpreter.\nSee
stdout/stderr for the exact error", "rc": 127}
and the below output
{ "module_stdout": "/bin/sh: /usr/bin/python3: No such file or
directory\r\n", "module_stderr": "Shared connection to 20.10.12.114
closed.\r\n", "msg": "The module failed to execute correctly, you
probably need to set the interpreter.\nSee stdout/stderr for the exact
error", "rc": 127, "_ansible_no_log": false, "changed": false }
For context, this is the version of Python I have installed:
[ec2-user#ip-20-10-12-114 ~]$ pip --version
pip 21.0.1 from /usr/lib/python3.6/site-packages/pip (python 3.6)
[ec2-user#ip-20-10-12-114 ~]$ which pip
/usr/bin/pip
[ec2-user#ip-20-10-12-114 ~]$ python --version
Python 2.7.18
[ec2-user#ip-20-10-12-114 ~]$ which python
/usr/bin/python
[ec2-user#ip-20-10-12-114 ~]$ python3 --version
Python 3.6.2
[ec2-user#ip-20-10-12-114 ~]$ which python3
/usr/bin/python3

Ansible "required for this module" dependency issue (with Linode module)

I've installed Ansible on Ubuntu and running:
ansible testserver -m linode -a 'state=stopped'
gives the error:
testserver | FAILED >> {
"failed": true,
"msg": "linode-python required for this module"
}
I installed linode-python successfully with pp install linode-python and I can run import linode in Python. So how can I get this module working?
Just to be sure : you have to install linode-python on the distant machine, not on the host.
Actually I realised this should be a local action, because we're not actually trying to run a command on the remote server. Which means I have to run this against localhost. So first I had to ensure I could ssh into localhost:
cd ~/.ssh; cat id_rsa.pub >> authorized_keys
Then I changed the machine to localhost:
ansible localhost -m linode -a 'state=stopped ...'
I'm still having some issues with that, but it seems to be running the module now.
Blogged it.

Categories

Resources