Why does my Ansible task hang? - ansible

I have the following ansible playbook:
- hosts: node1
sudo: yes
gather_facts: no
tasks:
- name: update apt
apt: update_cache=yes
- name: install python-setuptools
apt: name=python-setuptools update_cache=yes
- name: easy_install pexpect module
easy_install: name=pexpect state=latest
- name: add geonode repo
apt_repository: repo='ppa:geonode/stable' state=present
- name: update apt
apt: update_cache=yes
- name: install geonode
apt: name=geonode update_cache=yes
- expect:
command: geonode createsuperuser
responses:
(?i)username: 'test'
(?i)email: 'test#test.com'
When I run it I get:
PLAY [node1] *******************************************************************
TASK [update apt] **************************************************************
ok: [node1]
TASK [install python-setuptools] ***********************************************
changed: [node1]
TASK [easy_install pexpect module] *********************************************
changed: [node1]
TASK [add geonode repo] ********************************************************
changed: [node1]
TASK [update apt] **************************************************************
ok: [node1]
TASK [install geonode] *********************************************************
Then it hangs indefinitely.
In the remote node (node1), I checked the dir
/home/vagrant/.ansible/tmp/ansible-tmp-1470059145.13-122191240803512/
run the file inside to see why my task is hanging
vagrant#node1:~/.ansible/tmp/ansible-tmp-1470059145.13-122191240803512$ python apt
and get:
{"msg": "Failed to lock apt for exclusive operation", "failed": true, "invocation": {"module_args": {"dpkg_options": "force-confdef,force-confold", "autoremove": false, "force": false, "name": "geonode", "install_recommends": null, "package": ["geonode"], "purge": false, "allow_unauthenticated": false, "state": "present", "upgrade": null, "update_cache": true, "default_release": null, "only_upgrade": false, "deb": null, "cache_valid_time": null}}}
Do you have any insights?
EDIT 1:
It is all day I'm launching this script and never got it working. As I posted this question, obviously, the script successfully executed till the end in 15 minutes. I launched it before lunch today and after 1 hour it was still hanging. Why do I get such a different behaviour? Is there a way in which I can control it?

This issue might be caused by an empty /var/lib/apt folder.
Vagrant might take a while to populate these folders which could cause the apt lock.
Also the playbook is inefficient as update_cache is used multiple times. I would recommend to use something like this:
- hosts: node1
sudo: yes
gather_facts: no
tasks:
# Pause for 5 minutes to make sure vagrant does not hold apt lock.
- pause:
minutes: 5
- name: add geonode repo
apt_repository:
repo: 'ppa:geonode/stable'
state: present
- name: Install apt packages.
apt:
name: "{{ item }}"
state: present
update_cache: true
with_items:
- python-setuptools
- geonode
- name: Create geonode superuser.
expect:
command: geonode createsuperuser
responses:
(?i)username: 'test'
(?i)email: 'test#test.com'
This way Ansible won't update the repositories multiple times during the play.

Since the last thing you see is TASK [install geonode], that's where it's getting stuck.
You are asking it to run geonode createsuperuser which you expect to cause a prompt for username and password.
But what is likely happening is that there is an error being produced from that command, and the expect task is not handling the error, instead just hanging.
You can login to the server you are running this against and run the geonode createsuperuser command manually to see what error is being produced.
In my case, this was happening as a result of the username already being taken since I successfully ran the command on this machine already.
Error: That username is already taken.
Even with the echo: yes argument, ansible doesn't seem to pass on the responses to make it obvious what's happening. And it doesn't accept ignore_errors, so there seems to be no way to handle errors with the expect module.
To work around this, I added another task after the createsuperuser task which places a file in the project indicating the user was created once, and then added creates: {{ path }}/superuser_exists.txt to the createsuperuser task so that it won't run if that file is already there.
It's a hack, but an easy one, and until the module gets better error handling, it will work well enough.
- name: Create the django superuser
expect:
command: "{{ virtualenv_path }}/bin/python3 {{ project_path }}/{{ api_app_name }}/manage.py createsuperuser"
creates: "{{ project_path }}/{{ api_app_name }}/superuser_exists.txt"
responses:
(?i)username: "{{ superuser_username }}"
(?i)email: "{{ superuser_email }}"
(?i)password: "{{ superuser_password }}"
(?i)again: "{{ superuser_password }}"
- name: Create a file to indicate that the superuser was already created
file: path="{{ project_path }}/{{ api_app_name }}/superuser_exists.txt" state=touch

Related

How to use gather facts inside role?

I want to check if a package is installed but I get an error. Why the facts are not available inside the role?
TASK [docker : Check if listed package is installed or not on Debian Linux family] *****************************************************************************************************************************************************************
fatal: [10.100.0.52]: FAILED! => {"changed": false, "msg": "Could not detect which package manager to use. Try gathering facts or setting the \"use\" option."}
My playbook
- hosts: "{{ host }}"
gather_facts: yes
sudo: yes
roles:
- { role: "docker"}
and part of my role
- name: Check if listed package is installed or not on Debian Linux family
package:
name: ferm
state: present
check_mode: true
register: package_check
- name: Print execution results
debug:
msg: "Package is installed"
when: package_check is succeeded

Issue with AWX not with command line

I have a role in ansible working in command line but not through awx.
Here the role :
- name: Enable persistent logging
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: '^#Storage'
line: Storage=persistent
- name: Check directory
ansible.builtin.stat:
path: "{{ journal_dir }}"
register: journaldir
- block:
- name: Create directory
ansible.builtin.file:
path: "{{ journal_dir }}"
state: directory
mode: '0755'
- name: Enable systemd-tmpfiles folder
ansible.builtin.command: /bin/systemd-tmpfiles --create --prefix {{ journal_dir }}
check_mode: no
notify:
- restart systemd-journald
when: journaldir.stat.exists == false and ansible_distribution_major_version >= '7'
Here the notify code :
- name: restart systemd-journald
ansible.builtin.service:
name: systemd-journald
state: restarted
{{ journal_dir }} is /var/log/journal
I have no issue when I run the playbook on my terminal, but when I run it with awx, I still have this error :
TASK [journalctl : Enable systemd-tmpfiles folder] *****************************
fatal: [server]: FAILED! => {"changed": false, "msg": "no command given", "rc": 256}
I have done test also with shell module, it's the same behaviour.
And I don't understand why.
thank you for your help.
I foud the issue, it seems I'm using an old version of ansible, so I had to remove the fqcn for the command module.
It works like this :
- name: Enable systemd-tmpfiles folder
command: /bin/systemd-tmpfiles --create --prefix {{ journal_dir }}
notify:
- restart systemd-journald
my ansible version through command line is 2.9.27,ansible version of awx is 2.9.14.
[solution has been found here] : Ansible cant run any command or shell

fatal: [localhost]: FAILED! => {"changed": false, "msg": "Service is in unknown state", "status": {}}

This is my ansible playbook and I'm only running into an issue on the final task for starting and enabling Grafana.
---
- name: Install Grafana
hosts: hosts
become: yes
tasks:
- name: download apt key
ansible.builtin.apt_key:
url: https://packages.grafana.com/gpg.key
state: present
- name: Add Grafana repo to sources.list
ansible.builtin.apt_repository:
repo: deb https://packages.grafana.com/oss/deb stable main
filename: grafana
state: present
- name: Update apt cache and install Grafana
ansible.builtin.apt:
name: grafana
update_cache: yes
- name: Ensure Grafana is started and enabled
ansible.builtin.systemd:
name: grafana-server
state: started
enabled: yes
This is the error I received:
TASK [Ensure Grafana is started and enabled]
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Service is in unknown state", "status": {}}
This is also the configuration of my hosts file just in case:
[hosts]
localhost
[hosts:vars]
ansible_connection=local
ansible_python_interpreter=/usr/bin/python3
I'm pretty much just trying to have it run these two commands I have in a bash script
sudo systemctl start grafana-server
sudo systemctl enable grafana-server.service
Got it sorted out- turns out my system wasn't booted using systemd as init system. So I changed the Ansible module from ansible.builtin.systemd to ansible.builtin.sysvinit

Installing multiple php modules with ansible

I am trying to install multiple php modules with ansible
Here is the example of tasks:
- name: debug php modules
debug: msg="{{ php_version }}-{{ item }}"
with_items: php_modules
- name: php modules/extensions are installed
yum:
state=present
name="{{ php_version }}-{{ item }}"
with_items: "{{ php_modules }}"
when: php_modules is defined
and the actual variables defined:
vars:
php_version: php56u
php_modules:
- intl
- pdo
The playbook fails with "No Package matching 'pdo' found available, installed or updated"
I tried with with_items: php_modules and couldn't get it to work properly. It is strange because debug above works every time:
ok: [server-1] => (item=intl) => {
"item": "intl",
"msg": "php56u-intl"
}
ok: [server-1] => (item=pdo) => {
"item": "pdo",
"msg": "php56u-pdo"
}
A strange issue. I might be missing something very simple here?
Thanks to #udondan for the hint about debugging output of yum module. That helped a lot! It turns out ansible yum module tries to install everything at once and hence the list becomes something like "php56u-intl,pdo" instead of "php56u-intl,php56u-pdo" (hence the difference with the way "debug" module treats it, debug runs multiple times for each item but yum puts them all together).
The bug/feature/limitation was actually reported here: https://github.com/ansible/ansible/issues/5871
The trick, as one of the comments in the issue lists is to use "join", which forces yum module to run each item separately:
- name: php modules/extensions are installed
yum:
state=present
name={{ item|join('-') }}
with_nested:
- php_version
- php_modules
when: php_modules is defined
This is potentially the only way to do it until ansible yum module adds an option "one_by_one_install_please_please_please: true/false"

Ansible playbook error

I am testing with ansible, what I'm trying to do is install apache2 on another ubuntu server, I already have the group "test" defined with 1 ip. but what happens is that ansible throws me some errors when executing it, I've searched a lot of sites and a lot of people have had this issue, but on different situations and I amd starting to get frustrated with it. Can somebody help me?
Ansible Playbook:
---
- hosts: test
sudo: yes
tasks:
- name: Check if Im sudo
command: echo $USER
- name: install packages
apt: name:apache2 update_cache=yes state=latest
notify: start apache2
handlers:
- name: start apache2
service: name=apache2 state=started
STDOUT
root#ip-172-31-35-33:/etc/ansible/example# ansible-playbook example.yml
PLAY [test] *******************************************************************
GATHERING FACTS ***************************************************************
ok: [172.31.36.176]
TASK: [Check if Im sudo] ******************************************************
changed: [172.31.36.176]
TASK: [install packages] ******************************************************
failed: [172.31.36.176] => {"failed": true}
msg: this module requires key=value arguments (['name:apache2', 'update_cache=yes', 'state=latest'])
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit #/root/example.retry
172.31.36.176 : ok=2 changed=1 unreachable=0 failed=1
BTW, the host is reachable, I can ssh into it, even with ansible, this is the proof
root#ip-172-31-35-33:/etc/ansible/example# ansible -m shell -a "ifconfig | grep 'inet addr'" test
172.31.36.176 | success | rc=0 >>
inet addr:172.31.36.176 Bcast:172.31.47.255 Mask:255.255.240.0
inet addr:127.0.0.1 Mask:255.0.0.0
another thing is that I'm able to install apache2 by hand on the other server, BUT IT IS NOT INSTALLED BECAUSE I WANT TO INSTALL IT USING ANSIBLE
Thanks
Within an individual task, Ansible requires you to make the choice between standard YAML syntax and their own parsed version with equals signs. In this task, you are mixing the two:
- name: install packages
apt: name:apache2 update_cache=yes state=latest
notify: start apache2
This could be either written:
- name: install packages
apt:
name: apache2
update_cache: yes
state: latest
notify: start apache2
Or:
- name: install packages
apt: name=apache2 update_cache=yes state=latest
notify: start apache2
YAML also allows for using bracket and comma syntax to allow you to specify your key-value information on the same line:
- name: install packages
apt: {name: apache2, update_cache: yes, state: latest}
notify: start apache2
Any of these are valid.
You're using a colon where an equal is needed. You need to change the name:apache2 to name=apache2.

Resources