Ansible complains about "The MySQL-python module is required" - ansible

I have Ansible 2.6.1 installed in my local machine (WSL; Ubuntu):
ansible 2.6.1
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansile/plugins/modules']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.12 (default, Dec 4 2017, 14:50:18) [GCC 5.4.0 20160609]
My target machine is running Ubuntu 16.04-LTS.
I'm using this task to install python3-mysqldb:
- name: "Debian | Install Mysql Client package"
apt:
name: "{{ item }}"
state: present
with_items:
- mysql-client
- python3-dev
- libmysqlclient-dev
- python3-mysqldb
when:
- zabbix_server_database == 'mysql'
tags:
- zabbix-server
- init
- database
It fails in this task:
- name: "MySQL | Create database and import file >= 3.0"
mysql_db:
name: "{{ zabbix_server_dbname }}"
encoding: "{{ zabbix_server_dbencoding }}"
collation: "{{ zabbix_server_dbcollation }}"
state: import
target: "{{ ls_output_create.stdout }}"
when:
- zabbix_version is version_compare('3.0', '>=')
- zabbix_database_sqlload
- not done_file.stat.exists
delegate_to: "{{ delegated_dbhost }}"
tags:
- zabbix-server
- database
Here's the fail message:
fatal: [target_host -> target_host-db]: FAILED! => {"changed": false, "msg": "The MySQL-python module is required."}
I can confirm python3-mysqldb was indeed installed:
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/python3-mysqldb
/usr/share/doc/python3-mysqldb/changelog.Debian.gz
/usr/share/doc/python3-mysqldb/copyright
/usr/lib
/usr/lib/python3
/usr/lib/python3/dist-packages
/usr/lib/python3/dist-packages/mysqlclient-1.3.7.egg-info
/usr/lib/python3/dist-packages/mysqlclient-1.3.7.egg-info/top_level.txt
/usr/lib/python3/dist-packages/mysqlclient-1.3.7.egg-info/PKG-INFO
/usr/lib/python3/dist-packages/mysqlclient-1.3.7.egg-info/dependency_links.txt
/usr/lib/python3/dist-packages/_mysql_exceptions.py
/usr/lib/python3/dist-packages/_mysql.cpython-35m-x86_64-linux-gnu.so
/usr/lib/python3/dist-packages/MySQLdb
/usr/lib/python3/dist-packages/MySQLdb/connections.py
/usr/lib/python3/dist-packages/MySQLdb/release.py
/usr/lib/python3/dist-packages/MySQLdb/cursors.py
/usr/lib/python3/dist-packages/MySQLdb/constants
/usr/lib/python3/dist-packages/MySQLdb/constants/ER.py
/usr/lib/python3/dist-packages/MySQLdb/constants/CLIENT.py
/usr/lib/python3/dist-packages/MySQLdb/constants/REFRESH.py
/usr/lib/python3/dist-packages/MySQLdb/constants/FIELD_TYPE.py
/usr/lib/python3/dist-packages/MySQLdb/constants/FLAG.py
/usr/lib/python3/dist-packages/MySQLdb/constants/__init__.py
/usr/lib/python3/dist-packages/MySQLdb/constants/CR.py
/usr/lib/python3/dist-packages/MySQLdb/converters.py
/usr/lib/python3/dist-packages/MySQLdb/compat.py
/usr/lib/python3/dist-packages/MySQLdb/__init__.py
/usr/lib/python3/dist-packages/MySQLdb/times.py
I also tried installing the python package MySQL-python using pip but I also got the same error message.
I'm stumped. I don't know what to do anymore.
EDIT: I also tried installing Python 2.7.x on the target machine and made sure that /usr/bin/python is symlinked to Python 2.7.x but I'm still getting the same error. I'm using DJ Wasabi's zabbix-server role

I think you are mixing things up with your delegation. I would simplify things.
Option one: run everything locally. Assumes your DB server is reachable through the network:
- hosts: localhost
connection: local
tasks:
- name: "Debian | Install Mysql Client package"
apt:
name: "{{ item }}"
state: present
with_items:
- mysql-client
- python3-dev
- libmysqlclient-dev
- python3-mysqldb
when:
- zabbix_server_database == 'mysql'
tags:
- zabbix-server
- init
- database
- name: "MySQL | Create database and import file >= 3.0"
mysql_db:
name: "{{ zabbix_server_dbname }}"
encoding: "{{ zabbix_server_dbencoding }}"
collation: "{{ zabbix_server_dbcollation }}"
state: import
target: "{{ ls_output_create.stdout }}"
when:
- zabbix_version is version_compare('3.0', '>=')
- zabbix_database_sqlload
- not done_file.stat.exists
tags:
- zabbix-server
- database
Option two: run the SQL commands from the DB server (then you don't need mysql-python on your local machine, but you need python and mysql-python on the remote server hosting MySQL):
- hosts: dbserver
tasks:
- name: "Debian | Install Mysql Client package"
apt:
name: "{{ item }}"
state: present
with_items:
- mysql-client
- python3-dev
- libmysqlclient-dev
- python3-mysqldb
when:
- zabbix_server_database == 'mysql'
tags:
- zabbix-server
- init
- database
- name: "MySQL | Create database and import file >= 3.0"
mysql_db:
name: "{{ zabbix_server_dbname }}"
encoding: "{{ zabbix_server_dbencoding }}"
collation: "{{ zabbix_server_dbcollation }}"
state: import
target: "{{ ls_output_create.stdout }}"
when:
- zabbix_version is version_compare('3.0', '>=')
- zabbix_database_sqlload
- not done_file.stat.exists
tags:
- zabbix-server
- database

add ansible_python_interpreter in ansible.cfg as follows:
[test-server]
server1 ansible_ssh_host=x.x.x.x ansible_ssh_user=test ansible_python_interpreter=/usr/bin/python3

Related

The plugin community.general.dnf_versionlock dosent seem to work as intended

im trying to write an ansible playbock that updates all packages on a red hat machine and versionlocks them. when that is done. the list of locked packages chould then be exportet to a different machine.
it seems to work until the "lock all packeges stage". then it just freezes there.
what am i doing wrong?
thank you in advance.
---
- name: Update Red Hat system and lock version
hosts: "{{host}}"
become: true
vars:
locked_packages: "{{ locked_packages | default([]) + [ item.name ] }}"
tasks:
- name: debug host
debug:
msg: "{{host}}"
- name: unlock all packages
community.general.dnf_versionlock:
name: "*"
state: absent
- name: Update all packages
dnf:
name: '*'
state: latest
register: updated_packages_main
- name: print updated_packages_main variable
debug:
var: updated_packages_main
- name: lock all packages
community.general.dnf_versionlock:
name: "*"
state: present
register: locked_packages
- name: debug locked_packages
debug:
var: locked_packages
- name: send list of locked packages to remote host
fetch:
src: /etc/dnf/plugins/versionlock.list
dest: /opt/locked_packages.txt

How do I correct ansible playbook syntax error? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last year.
Improve this question
I am creating an ansible playbook in centos7. I get the syntax error every-time I adjust to the syntax error (I even checked spacing and still getting same error):
ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: No JSON object could be decoded
Syntax Error while loading YAML.
could not find expected ':'
The error appears to be in '/etc/ansible/playbook.yml': line 121, column 5, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Install MySQL repo
^ here
hosts: local host
connection: local
vars: digital_ocean_token: ****
droplets:
- wordpress1
- wordpress2
tasks:
- name: Create SSH Key
user:
name: "{{ansible_user_id}}"
generate_ssh_key_type: rsa
ssh_key_type 4096
ssh_key_file .ssh/id_rsa
- name: Create Digital Ocean Key
community.digitalocean.digital_ocean:
state: present
command: droplet
name: "" "{{ item }}"
unique_name: yes
size_id: s-1vcpu-1gb
region_id: nyc
image_id: centos-7-x64
ssh_key_ids: "{{ my_ssh.ssh_key.id }}"
api_token: "{{ digital_ocean_token }}"
with_items: "{{droplets}}"
register: droplet_details
- name: Add doplets to /etc/ansible/hosts
add_host:
path: /etc/ansible/hosts
groups: droplets
name: "{{ item.droplet.ip_address }}"
with_items:: "{{ droplet_details.results }}"
- pause:
seconds: 45
- hosts: droplets
tasks:
- name: Disable SeLinux
selinux:
state: disabled
#Epel-Release
- name: Install epel-release
yum:
name: epel-release
state: present
- name: update
yum:
name: "*"
state: present
#Install Apache
- name: Install Apache
yum:
name: httpd
state: latest
- name: enable service to start on boot up
service:
name: httpd
state: started
#Install MariaDB
- name: Install MariaDB
yum:
name: mariadb
state: latest
- name: Install MariaDB Server
yum:
name: mariadb-server
state: latest
- name: Install Python2
yum:
name: python2
state: latest
- name: Install Python3
yum:
name: python3
state: latest
- name: Install pip
pip:
name: pip
extra_args: --upgrade
executable: pip3
#Install PHP
- name: Install Remi Repository
yum:
name: https://rpms.remirepo.net/enterprise/remi-release-7.rpm
state: present
- name: Install PHP
yum:
enablerepo: "remiremi-php80"
name:
- php
- php-common
- php-cli
- php-gd
- php-curl
- php-mysqlnd
- php-fpm
- php-mysqli
- php-json
state:latest
- name: Install MySQL repo
yum:
name: http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
state: present
- name: Install PyMySQL
yum:
pkg: ['mysql-community-server', 'mysql-community-client', 'MySQL-python']
# Start MySQL
- name: Start MySQL
service:
name: mysqld
state: started
enabled: yes
# Create MariaDB Database
- name: MySQL login
mysql_user:
user: ***
login_user: ***
login_password: "****"
state: present
- name: Create MariaDB username & password
mysql_user:
login_user: ****
login_password: "****!"
name: wordpressuser
password: ****
priv: "*.*;ALL,GRANT"
host: "localhost"
state: present
- name: Vreate MariaDB Database
mysql_db:
login_user: ***
login_password: "****"
state: present
- name: Restart MariaDB Database
service:
name: mysqld
state: restarted
# Install Wordpress
- name: Download Wordpress
get_url:
url=http://wordpress.org/latest.tar.gz
dest=/tmp/wordpress.latest.tar.gz
validate_certs=no
- name: unzip Wordpress
unarchive:
src=/tmp/wordpress.latest.tar.gz
dest=/var/www
copy=no
- name: Copy sample config file
command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php
- name: Update Wordpress config file
lineinfile:
path: /var/www/wordpress/wp-config.php
regexp: "{{item.regexp}}"
line: "{{item.line}}"
with_items:
- {'regexp': "define\\( 'DB_NAME', '(.)+' \\);", 'line': "define( 'DB_NAME'', 'wordpress');"}
- {'regexp': "define\\( 'DB_USER', '(.)+' \\);", 'line': "define( 'DB_USER', 'wordpressuser' );"}
- {'regexp': "define\\( 'DB_PASSWORD', '(.)+' \\);", 'line': "define( 'DB_PASSWORD', '***' );"}
- name: Give Ownership to Apache user
file:
path: /var/www/wordpress
state" directory
recurse: yes
owner: apache
group: apache
- name: Set correct permissions on Wordpress directories
command: find /var/www/wordpress/ -type d -exec chomd 755 {} \;
- name: Set correct permissions for Wordpress files
command: find /var/www/wordpress/ -type f -exec chomd 755 {} \;
- name: Restart Apache
service:
name: httpd
state: restarted
It looks from what you provided that you don't have a valid yaml format playbook.
You can do quick syntax checks using:
ansible-playbook playbook.yaml --syntax-check
The plays need to be one or more elements of a yaml list, under tasks.
I'd expect your playbook to look something like:
---
# YAML documents begin with the document separator ---
- hosts: hosta,hostb ...etc
tasks:
- name: install MySQL repo
yum:
name: http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
state: present
# Three dots indicate the end of a YAML document
...
There are other sections you might have in a playbook, but I've omitted those. The sections like vars, handlers or roles, would be list items at the same indention level as the hosts: and tasks: if you were to need those.
It looks like your issue is here:
name: Install PHP
yum:
enablerepo: "remiremi-php80"
name:
- php
- php-common
- php-cli
- php-gd
- php-curl
- php-mysqlnd
- php-fpm
- php-mysqli
- php-json
state: latest
Notice that state: has to be indented exactly at the same level as enablerepo and name. Make sure you have a space there between state: and latest.

unpacking yaml values in the ansible playbook

i'm a fresher in the professional world as i just joined amid corona situation as being work from i have been involved to understand and write ansible codes and at some level i am growing up by watching through SO posts to get variety of ticks & tricks.
I have the below ansible playbooks..
1- One is custom_pkgs.yml which basically installing some custom build packages using yum command where it calling a pkgs.yml file which lists the packages to be install.
I somewhat understood the code but
$ vi custom_pkgs.yml
---
- name: Install License
hosts: all
become: yes
become_user: root
become_method: sudo
tasks:
- name: Include the variables to install the license software
include_vars:
file: "vars/pkg.yml"
name: license
- name: Install license software
shell: "yum install -y {{ license[ item ] | join(' ') }}"
with_items: "{{ license }}"
changed_when: True
when: item != "remove"
- name: Remove any unwanted RPMS
shell: "yum remove -y {{ license.remove | join(' ') }}"
changed_when: True
when: license.remove is defined
...
Below is the pkg.yml
$ cat pkg.yml
---
license:
- fenixlmd.noarch
- tmpwatch
- xorg-x11-deprecated-libs.i386
- Tasking.noarch
- rotate_fix.noarch
- plexim.noarch
- interrad.noarch
- idsd.noarch
- gsi.noarch
- java-1.8.0-openjdk
- java-1.8.0-openjdk-devel
- java-1.8.0-openjdk-debug
- flexnet_agent
- magillem.noarch
- redhat-lsb-printing
- redhat-lsb-printing.i686
- redhat-lsb-core
- redhat-lsb-core.i686
- redhat-lsb
- redhat-lsb.i686
- git
- gcc
- python-devel
...
What i would like to Know:
I am trying to understand about below two lines..
shell: "yum install -y {{ license[ item ] | join(' ') }}" and when: item != "remove"
I have went through all the basics of asking question in SO in case i've ask something out of way i would like to be excused as this is my first post.
Regards ..
Thanks for learning Ansible, this is an old Ansible code. The pkg.yml file defines a list variable called licence containing a list of yum package to install on the remote host using the Ansible shell module. with_items: "{{ license }}" tell the module to iterate on that variable items.
The When condition help to skip the package when his name is remove.
Read the Ansible conditional documentation: https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#the-when-statement
But as i told, it's an old code. On Ansible recent version, you will use a yum module to install yum package (create two lists of package: package_to_install and package_to_remove
- name: Install License
hosts: all
become: yes
become_user: root
become_method: sudo
tasks:
- name: Include the variables to install the license software
include_vars:
file: "vars/pkg.yml"
name: license
- name: Install license software
yum:
name: "{{ package_to_install }}"
changed_when: True
when: item != "remove"
- name: Remove any unwanted RPMS
yum:
name: "{{ package_to_remove }}"
state: absent
changed_when: True
Make sure to use a recent Ansible version (2.9).
Read the yum module documentation: https://docs.ansible.com/ansible/latest/modules/yum_module.html
You can Also defined only one list of package variable with two fields:
license:
- { name: fenixlmd.noarch, state: present }
- { name: tmpwatch, state: absent }
- { name: xorg-x11-deprecated-libs.i386, state: present }
.
.
.
And then use the yum module like that:
- name: Install License
hosts: all
become: yes
become_user: root
become_method: sudo
tasks:
- name: Include the variables to install the license software
include_vars:
file: "vars/pkg.yml"
name: license
- name: Remove any unwanted or install needs package RPMS
yum:
name: "{{ item.name }}"
state: "{{ item.state }}"
with_items: "{{ licence }}"

Installing multiple packages in Ansible

I have this task in Ansible:
- name: Install mongodb
yum:
name:
- "mongodb-org-{{ mongodb_version }}"
- "mongodb-org-server-{{ mongodb_version }}"
- "mongodb-org-mongos-{{ mongodb_version }}"
- "mongodb-org-shell-{{ mongodb_version }}"
- "mongodb-org-tools-{{ mongodb_version }}"
state: present
notify: Restart mongodb
Is there a way I can indicate the version without having to use a loop like this? What is a more "elegant" way of writing this?
- name: Install mongodb
yum:
name: "{{ item }}-{{ mongodb_version }}"
state: present
loop:
- mongodb-org-server
- mongodb-org-mongos
- mongodb-org-shell
- mongodb-org-tools
notify: Restart mongodb
To my surprise I didn't find the simplest solution in all the answers, so here it is. Referring to the question title Installing multiple packages in Ansible this is (using the yum module):
- name: Install MongoDB
yum:
name:
- mongodb-org-server
- mongodb-org-mongos
- mongodb-org-shell
- mongodb-org-tools
state: latest
update_cache: true
Or with the apt module:
- name: Install MongoDB
apt:
pkg:
- mongodb-org-server
- mongodb-org-mongos
- mongodb-org-shell
- mongodb-org-tools
state: latest
update_cache: true
Both modules support inline lists!
The second part of your question is how to integrate specific version numbers into the package lists. No problem - simply remove the state: latest (since using specific version numbers together with state: latest would raise errors) and add the version numbers to the package names using a preceding = like this:
- name: Install MongoDB
yum:
name:
- mongodb-org-server=1:3.6.3-0centos1.1
- mongodb-org-mongos=1:3.6.3-0centos1.1
- mongodb-org-shell=1:3.6.3-0centos1.1
- mongodb-org-tools=1:3.6.3-0centos1.1
update_cache: true
You could also optimize further and template the version numbers. In this case don't forget to add quotation marks :)
Make this into an Ansible Role called mongo, resulting in the directory structure:
playbook.yml
roles
|-- mongo
| |-- defaults
| | |-- main.yml
| |
| |-- tasks
| | |-- main.yml
| |
| |-- handlers
| | |-- main.yml
Add the required MongoDB packages and version into the default variables file roles/mongo/defaults/main.yml:
mongo_version: 4.0
mongo_packages:
- mongodb-org-server
- mongodb-org-mongos
- mongodb-org-shell
- mongodb-org-tools
Re-write the task in the roles/mongo/tasks/main.yml file:
- name: Install mongodb
yum:
name: "{{ item }}-{{ mongo_version }}"
state: present
with_items: "{{ mongo_packages }}"
notify: Restart mongodb
Add your handler logic to restart MongoDB in the file roles/mongo/handlers/main.yml.
Write a Playbook called playbook.yml that calls the role.
---
- hosts: all
roles:
- mongo
Some people have mentioned syntax that allows passing a list, but you don't need to special-case your code for apt or yum. Here is the command that uses the generic package manager module:
- name: Install packages
become: yes
package:
name:
- tmux
- rsync
- zsh
- rsync
- wget
state: present
(Or state: latest.) This feature is only documented for Ansible 2.9, so it may be new.
I think this is best way, but as the package names should not be hard coded, it is preferred to keep in vars/main.yml
e.g
mongodb_version: 5
packages:
- "mongodb-org-shell-{{ mongodb_version }}"
- "mongodb-org-server-{{ mongodb_version }}"
Call this inside your playbook as
- name: Install mongodb packages
yum: name={{ item }}
state=latest
with_items: "{{ packages}}"
Now yum module direct accept array of packages like this
vars:
pkgs:
- screen
- rubygems
- ksh
- strace
tasks:
- name: Install pre-requisite packages
yum: name={{ pkgs }} state=installed
A more elegant way, which doesn't keep re-checking each and every package if installed every time the script is run is to use something like this:
In vars/main.yml or similar:
packages_to_install:
- mongodb-org-server
- mongodb-org-mongos
- mongodb-org-shell
- mongodb-org-tools
In tasks/main.yml or similar:
- name: "Get installed packages"
yum:
list: "installed"
register: installed_packages
- name: "Install missing packages"
package:
state: "present"
name: "{{ item }}"
with_items: "{{ packages_to_install | difference(installed_packages | json_query('results[*].name')) }}"
Essentially this checks what is already installed and only installs missing packages. Counter-intuitively this is faster. You can also use dnf instead of yum.

ansible playbook error at -name

Hi i have an error when running the following ansible-playbook:
(i am trying to install a LAMP stack and wordpress on my virtual machine)
The error seems like it's coming from the database.
Are mysql_db and mysql_user valid commands to create database and user ?
Please help, Thank you.
---
- hosts: vbox
remote_user: arnold
become: yes
become_method: sudo
vars:
MySQL_root_pass: root_pass
dbase: dbwordpress
user: wp_user
parola: wp_pass
tasks:
- name: Linux update
apt: update_cache=yes
- name: Linux upgrade
apt: upgrade=safe
async: 600
poll: 5
- name: Install apache
apt: pkg=apache2 state=installed
notify:
- start apache
- name: Set MySQL root password before installing
debconf: name='mysql-server' question='mysql-server/root_password' value='{{MySQL_root_pass | quote}}' vtype='password'
- name: Confirm MySQL root password before installing
debconf: name='mysql-server' question='mysql-server/root_password_again' value='{{MySQL_root_pass | quote}}' vtype='password'
- name: Install mysql
apt: name={{ item }} state=installed
with_items:
- mysql-server
- libapache2-mod-auth-mysql
- pkg=php5-mysql
notify:
- start mysql
- name: Install php
apt: name={{ item }} state=installed
with_items:
- php5
- libapache2-mod-php5
- php5-mcrypt
notify:
- restart apache
- name: Create database and user for wordpress
mysql_db: name={{ dbase }} state=present
mysql_user: name={{ user }} password={{ parola }} priv=dbwordpress.*:ALL state=present
notify:
- restart mysql
- name: Install wordpress
command: "{{ item }}"
with_items:
- cd ~
- wget http://wordpress.org/latest.tar.gz
- tar xzvf latest.tar.gz
- cd ~/wordpress
- cp wp-config-sample.php wp-config.php
- name: Config wordpress
lineinfile: dest=~/wordpress/wp-config.php {{ item }}
with_items:
- regexp=^DB_NAME line="define('DB_NAME', '{{ dbase }}');"
- regexp=^DB_USER line="define('DB_USER', '{{ user }}');"
- regexp=^DB_PASSWORD line="define('DB_PASSWORD', '{{ parola }}');"
- name: Copy files to root document
command: "{{ item }}"
with_items:
- rsync -avP ~/wordpress/ /var/www/html/
- cd /var/www/html
- chown -R arnold:arnold *
handlers:
- name: start apache
service: name=apache state=started
- name: start mysql
service: name=mysql state=started
- name: restart mysql
service: name=mysql state=restarted
- name: restart apache
service: name=php state=restarted
And the error code:
ERROR! conflicting action statements
The error appears to have been in '/home/arnold/Documents/wordpress': line 49, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Create database and user for wordpress
^ here
The error appears to have been in '/home/arnold/Documents/wordpress': line 49, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Create database and user for wordpress
^ here
You have two modules mysql_db and mysql_user under one task:
- name: Create database and user for wordpress
mysql_db: name={{ dbase }} state=present
mysql_user: name={{ user }} password={{ parola }} priv=dbwordpress.*:ALL state=present
notify:
- restart mysql
Spilt them into two tasks:
- name: Ensure the database for WordPress exists
mysql_db: name={{ dbase }} state=present
notify:
- restart mysql
- name: Ensure the user for WordPress exists
mysql_user: name={{ user }} password={{ parola }} priv=dbwordpress.*:ALL state=present
notify:
- restart mysql

Resources