or condition in ansible skips the hosts that are not matched in condition

29 views
Skip to first unread message

shashank pai

unread,
Nov 20, 2017, 1:15:41 AM11/20/17
to Ansible Project

I am trying to check memory consumption of four machines and any of the machines memory consumption is less than 10 GB I want to restart services on all machines.

I have used or operator in when condition, I am able to restart the services only on the ones that have memory less than 10 GB others get skipped. My requirement is if any of the hosts memory goes down below 10GB I want services to be restarted on all machines not just on machines that have memory below 10GB.

Below is the Ansible playbook:


- hosts: webapp
become: true
become_method: sudo
gather_facts: yes
vars:
servers:
"10.0.0.1": "machine1"
"10.0.0.2": "machine2"
"10.0.0.3": "machine3"
"10.0.0.4": "machine4"
tasks:
- name: get mem free for machine1
shell: free -g | grep Mem | awk '{print $4}'
register: machine1_mem
- debug: var=machine1_mem.stdout
when: servers[ansible_default_ipv4.address] == "machine1"
- name: get mem free for machine2
shell: free -g | grep Mem | awk '{print $4}'
register: machine2_mem
- debug: var=machine2_mem.stdout
when: servers[ansible_default_ipv4.address] == "machine2"
- name: get mem free for machine3
shell: free -g | grep Mem | awk '{print $4}'
register: machine3_mem
- debug: var=machine3_mem.stdout
when: servers[ansible_default_ipv4.address] == "machine3"
- name: get mem free for machine4
shell: free -g | grep Mem | awk '{print $4}'
register: machine4_mem
- debug: var=machine4_mem.stdout
when: servers[ansible_default_ipv4.address] == "machine4"
- name: restart web services
when: ( machine4_mem.stdout|int <= 10 or machine1_mem.stdout|int <= 10 or machine3_mem.stdout|int <= 10 or machine2_mem.stdout|int <= 10 )
      action: service name=httpd state=restarted


Pshem Kowalczyk

unread,
Nov 20, 2017, 2:52:39 AM11/20/17
to ansible...@googlegroups.com
Ansible operates on an internal loop. Tasks are executed (and facts set) on 'per-device' basis. If you need the results of all the checks I suggest you do the following:

1. Register the results and store them into files on the controller (either can run as internal ansible loop or manual set of tasks)
2. Add another play in your playbook that's executed on the localhost - check the content of each of the files and identify if you have to restart or not. You can store this as a fact against 'localhost' so it's accessible via hostvars['localhost']['var_name']
3. Add yet another play that conditionally restarts all the servers if the content of the variable indicates the need for a restart

the whole thing can be also done without storing info in the files - you can loop over all hosts in a group so you can access the results of the check. 

kind regards
Pshem


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/be9b8961-8013-444f-8c99-1939d25b6757%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

shashank pai

unread,
Nov 21, 2017, 7:24:51 AM11/21/17
to Ansible Project
Thanks Pshem for your solution, Is there anything i can use as ANY condition like if any of the servers return value less than 10 do a service restart on all servers. Below is my play book which i tried.


--- # first playbook 
- hosts: apacheweb
  remote_user: ansible
  become: true
  become_method: sudo
  gather_facts: yes
  tasks:
    - name: Register free memory
      shell: free -g | grep Mem | awk '{print $4}'
      register: memory
    - set_fact: mem={{ memory.stdout }}
    - set_fact: Mem_check=False
      when: mem|int > 10
    - name: Restart web service
      service:
        name: httpd
        state: restarted
      when: not Mem_check


Here i am trying to use set_fact with boolean values if it changes to True from false do a restart on all machines . But still it is only restarting the services on machines that are effected. 

Kai Stian Olstad

unread,
Nov 22, 2017, 12:05:10 PM11/22/17
to ansible...@googlegroups.com
This is a little ugly but should work

- name: Restart web service
service:
name: httpd
state: restarted
when: {{ group['apacheweb'] | map('extract', hostvars) | list | selectattr('Mem_check') | list | length < group['apacheweb'] | length }}


One possible caveat, if one or more host doesn't respond the service on the host that work will restarted.


--
Kai Stian Olstad
Reply all
Reply to author
Forward
0 new messages