When a (pretty basic) Ansible playbook was run against a SLES 15 SP1 client, the playbook already stopped after the first few tasks with a Python related error message:
TASK [MONI - Install Nagios packages (SLES10/11)] ******************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ImportError: No module named xml
failed: [sles15.local] (item=[u'nrpe', u'nagios-plugins-all', u'ksh', u'sysstat']) => {"ansible_loop_var": "item", "changed": false, "item": ["nrpe", "nagios-plugins-all", "ksh", "sysstat"], "module_stderr": "Shared connection to 10.161.208.42 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/ansible/.ansible/tmp/ansible-tmp-1599726118.74-10511-262880492763867/AnsiballZ_zypper.py\", line 102, in
PLAY RECAP ******************************************************************************************
sles15.local : ok=1 changed=0 unreachable=0 failed=1 skipped=7 rescued=0 ignored=0
On the SLES 15 machine, this can quickly be verified by manually trying to import the xml module into Python:
sles15:~ # python
Python 2.7.17 (default, Nov 04 2019, 16:08:54) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml
Traceback (most recent call last):
File "
ImportError: No module named xml
Obviously an older Python 2.7 is used here as default Python version - even though Python 3.6 is installed at the same time.
The obvious solution is to simply install the missing module/library from the package manager (zypper). However when looking for the relevant package (libxml2-python), only the source package python-libxml2-python was available for Python 2 - while the "normal" package python3-libxml2-python was available for Python 3:
sles15:~ # zypper se libxml2-python
Refreshing service 'Basesystem_Module_15_SP1_x86_64'.
Refreshing service 'SUSE_Linux_Enterprise_Server_15_SP1_x86_64'.
Refreshing service 'SUSE_Package_Hub_15_SP1_x86_64'.
Refreshing service 'Server_Applications_Module_15_SP1_x86_64'.
Loading repository data...
Reading installed packages...
S | Name | Summary | Type
---+------------------------+-----------------------------+-----------
| python-libxml2-python | Python Bindings for libxml2 | srcpackage
| python3-libxml2-python | Python Bindings for libxml2 | package
Installing the python3-libxml2-python package was easy:
sles15:~ # zypper in python3-libxml2-python
Refreshing service 'Basesystem_Module_15_SP1_x86_64'.
Refreshing service 'SUSE_Linux_Enterprise_Server_15_SP1_x86_64'.
Refreshing service 'SUSE_Package_Hub_15_SP1_x86_64'.
Refreshing service 'Server_Applications_Module_15_SP1_x86_64'.
Loading repository data...
Reading installed packages...
Resolving package dependencies...
The following NEW package is going to be installed:
python3-libxml2-python
1 new package to install.
Overall download size: 221.0 KiB. Already cached: 0 B. After the operation, additional 1.6 MiB will be used.
Continue? [y/n/v/...? shows all options] (y): y
Retrieving package python3-libxml2-python-2.9.7-3.22.1.x86_64 (1/1), 221.0 KiB ( 1.6 MiB unpacked)
Retrieving: python3-libxml2-python-2.9.7-3.22.1.x86_64.rpm ........................[done]
Checking for file conflicts: ......................................................[done]
(1/1) Installing: python3-libxml2-python-2.9.7-3.22.1.x86_64 ......................[done]
And importing the xml module in Python 3 was working, too:
sles15:~ # python3
Python 3.6.10 (default, Dec 19 2019, 15:48:40) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml
>>> exit()
However the Ansible playbook run still failed due to the same error message. Obviously Python 2 is used by default, as python on this SLES 15 machine points to Python 2:
sles15:~ # ll /usr/bin/python
lrwxrwxrwx 1 root root 9 May 4 18:01 /usr/bin/python -> python2.7
And the missing libxml2 library could not be installed for Python 2 on this SLES 15 machine...
A possible quick and dirty fix would be to change the symlink to point to /usr/bin/python3 - but maybe other scripts are running on this SLES 15 machine which rely on Python 2 and this could potentially break a lot of things. But there's a better way!
Ansible can be told which Python version should be used on the client. By using the setting ansible_python_interpreter, a specific Python path/version can be defined on a per client basis (hint found in Ansible issue 59686):
ansible@ansibleserver:~$ grep -h sles15 inventory/*
sles15.local ansible_ssh_host=10.161.208.42 ansible_python_interpreter=/usr/bin/python3
The playbook now runs with Python 3 on the SLES 15 machine and finally finished with success:
PLAY RECAP *****************************************************************************************
sles15.local : ok=14 changed=6 unreachable=0 failed=0 skipped=24 rescued=0 ignored=0
As suggested in the comments, another possibility is to use update-alternatives to point /usr/bin/python to /usr/bin/python3.
Wow. The counter increased to a four digit number now! This is my 1000th blog post! It took me more than 12 years to achieve this number. The first blog post (Welcome to claudiokuenzler.com) was published on May 26th 2008. A long time ago. Back then virtual machines was the current and still upcoming hype. Nobody talked of containers let alone Kubernetes back then.
But not only technical stuff surrounding me changed - in the meantime I married and became a father or two wonderful (most of the times anyway) kids. Besides this I co-founded Infiniroot where customer tasks and project have a priority. This clearly takes a lot of my time.
Will there be a 2000th entry in the future? Only time will tell. But it will clearly be difficult. But as long as there are still challenges left to resolve (oh yes, there will), new blog articles will continue to roll in.
Glowsome from Netherlands wrote on Jun 26th, 2021:
You can also use alternatives to point to the correct python3 version after installing the suggested RPM (python3-libxml2-python)
execute : update-alternatives --install /usr/bin/python python /usr/bin/python3 300
output: update-alternatives: using /usr/bin/python3 to provide /usr/bin/python (python) in auto mode
check : update-alternatives --display python
output: python - auto mode
link best version is /usr/bin/python3
link currently points to /usr/bin/python3
link python is /usr/bin/python
/usr/bin/python3 - priority 300
Double-check: ll /usr/bin/python
output: lrwxrwxrwx 1 root root 24 Jun 26 00:35 /usr/bin/python -> /etc/alternatives/python
Rafael from São Paulo - Brazil wrote on Sep 11th, 2020:
By the way, man. Congratz on the post 1000.
Rafael from wrote on Sep 10th, 2020:
Hi Claudio. It was the same error that you have shared. For me was necessary to install the python-xml package too. Now it is working! Thank you, man.
ck from Switzerland wrote on Sep 10th, 2020:
Hi Rafael. So what's the exact error? Also ImportError on xml? Are you sure the Ansible client is running on Python 3? Is this a SLES15, too?
Rafael from wrote on Sep 10th, 2020:
Mna, same error here, and to install the xml didn't work.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Database Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Office PGSQL PHP Perl Personal PostgreSQL Postgres PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder