user4889345
user4889345

Reputation:

Ansible hosts preference

I am trying to run some yum commands on remote set of nodes. But they need to be run in a particular sequence and not in parallel.

---
- name: Java 1.8 upgrade for EFM on Witness
  hosts: database-witness:database-standby:database-master
  tasks:
  - name: Installating Java 1.8 on Witness
    yum: name=java-1.8.0-openjdk-1.8.0.111-2.b15.el7_3 state=present
    notify: set unlimited java 1.8 security
  - name: Remove Java 1.7
    shell: rm -f /usr/lib/jvm/$(ls /usr/lib/jvm | grep "java-1.7")/jre/lib/security/*.jar
  - name: Remove SDK
    yum: name=java-1.7.0-openjdk.x86_64 state=absent
  - name: Remove Headless
    yum: name=java-1.7.0-openjdk-headless.x86_64 state=absent

My env file is ::

[database-master]
172.X.X.1

[database-standby]
172.X.X.2

[database-witness]
172.X.X.3

In the above playbook I've specified:

hosts: database-witness:database-standby:database-master

Does this mean the set of yum commands will first be run on database-witness THEN on database-standby and THEN on database-master.

Upvotes: 1

Views: 195

Answers (2)

techraf
techraf

Reputation: 68609

In the above playbook I've specified:

hosts: database-witness:database-standby:database-master

Does this mean the set of yum commands will first be run on database-witness THEN on database-standby and THEN on database-master.

No. Ansible runs playbooks using a specified strategy. By default (linear strategy), Ansible will fork five threads and run each task in parallel on five hosts. Ansible will move to the next tasks only when all hosts in the current group finished (or failed).

Since you want to move to the next host after all tasks on a single host finished, the default strategy will not work for you.


You can add a serial: 1 declaration (see Rolling Update Batch Size) to the play which will cause Ansible to run all tasks on a single host before proceeding to the next one, but the question of the order remains.

Theoretically hosts' list is ordered and once you get it empirically tested it should be repeatable, but there was a (small) number of examples in questions on SO which suggested that Ansible is not always keeping the "common-sense" order.

---
- name: Java 1.8 upgrade for EFM on Witness
  hosts: database-witness:database-standby:database-master
  serial: 1
  tasks:
    # the tasks

But if you have a strict requirement like in your question, the most reliable way would be to split your play into three.

You can extract the tasks to a separate file to avoid duplication. So:

---
- name: Java 1.8 upgrade for EFM on Witness
  hosts: database-witness
  tasks:
    - include: tasks.yml

- name: Java 1.8 upgrade for EFM on Witness
  hosts: database-standby
  tasks:
    - include: tasks.yml

- name: Java 1.8 upgrade for EFM on Witness
  hosts: database-master
  tasks:
    - include: tasks.yml

And tasks.yml:

- name: Installating Java 1.8 on Witness
  yum: name=java-1.8.0-openjdk-1.8.0.111-2.b15.el7_3 state=present
  notify: set unlimited java 1.8 security
- name: Remove Java 1.7
  shell: rm -f /usr/lib/jvm/$(ls /usr/lib/jvm | grep "java-1.7")/jre/lib/security/*.jar
- name: Remove SDK
  yum: name=java-1.7.0-openjdk.x86_64 state=absent
- name: Remove Headless
  yum: name=java-1.7.0-openjdk-headless.x86_64 state=absent

The latter solution also makes sure the execution will stop in case of an error on any host. With serial: 1-method you have no such guarantee, so if the tasks failed on database-witness, Ansible would proceed with the next target.

Upvotes: 1

Giuseppe Scrivano
Giuseppe Scrivano

Reputation: 1635

They will run in parallel on the different hosts, on each host these tasks run sequentially

Upvotes: 0

Related Questions