this is my task/main.yml:
- name: Create and start services
docker_compose: ...
and I have 3 hosts. I'd like this task will be run on each host with 3 minute intervals.
for example: running on host1 at minute 0, running on host2 at minute 3 and running on host3 at minute 6.
How can I do that?
There's "pause" available in ansible playbook. Have you tried it?
Here is the official doc : https://docs.ansible.com/ansible/latest/modules/pause_module.html
As per this doc,
To pause/wait/sleep per host, use the wait_for module.
you can use "wait_for" module : https://docs.ansible.com/ansible/latest/modules/wait_for_module.html#wait-for-module
Code snippet which you can use for "pause" :
tasks:
- name: Test
pause:
minutes: 2
- name: Echo
debug:
msg: Test Pause
Code snippet for "wait_for"
tasks:
- name: sleep for 120 seconds and continue with play
wait_for:
timeout: 120
- name: Echo
debug:
msg: Test Pause
Related
There are few hosts, where ssh will be talking lot of time/forever to give prompt, in this case my playbook wait forever
Here,I want to skip/kill the task after waiting max 1min (60sec).
This is my playbook
- name: uname
# shell: uname -a;hostname
command: timeout 20 uname -a;hostname #tried but no luck
async: 60
poll: 0
register: yum_sleeper
- name: 'Verify the job status'
async_status: jid={{ yum_sleeper.ansible_job_id }}
register: output
until: output.finished
retries: 6
delay: 10
ignore_errors: true
The stange part here is that, the "uname" task is not started at all on target host as that host never give prompt after ssh, so what ever command I mentioned in task are not going to perform.
The playbook output as like below
Using /root/.ansible.cfg as config file
PLAY [all] *******************************************************************************
I also ran the first ansible "ping" command that also stuck
ansible -i invetory_file web -m ping
Please suggest
With the fork variable I can tell ansible how many hosts should pe executed in parallel. The next hosts are executed when all hosts from before finished. In case the execution time differs on the hosts, I have to wait for the last host finishing.
Is it possible to tell ansible start the next play for one host after one has finished, not all running.
In other words, I have hundreds clients with a play running at 5 minutes and some hosts need 30 minutes. We tested the amount of fork and found that 50 is a good value. Sometimes the next 50 had to wait for one host 25 minutes.
Q: "Is it possible to tell Ansible to start the next play for one host after one has finished?"
A: Yes. It's possible. The strategy plugin host_pinned is what you're looking for. Quoting:
Ansible will not wait for other hosts to finish the current task before queuing the next task for a host that has finished. Once a host is done with the play, it opens its slot to a new host that was waiting to start.
Example
Lets' create an inventory
shell> cat hosts
all:
hosts:
test_01:
wait_timeout: 1
test_02:
wait_timeout: 2
test_03:
wait_timeout: 3
test_06:
wait_timeout: 4
test_09:
wait_timeout: 5
The playbook below
shell> cat pinned-01.yml
- name: Play A
hosts: all
gather_facts: false
strategy: host_pinned
tasks:
- debug:
msg: "A:{{ inventory_hostname }}
{{ lookup('pipe', 'date +%H-%M-%S') }}
started"
- wait_for:
timeout: "{{ wait_timeout }}"
- debug:
msg: "A:{{ inventory_hostname }}
{{ lookup('pipe', 'date +%H-%M-%S') }}
finished"
gives
shell> ansible-playbook pinned-01.yml -f 3 | grep msg\":
"msg": "A:test_06 15-33-05 started"
"msg": "A:test_09 15-33-05 started"
"msg": "A:test_01 15-33-05 started"
"msg": "A:test_01 15-33-08 finished"
"msg": "A:test_02 15-33-08 started"
"msg": "A:test_06 15-33-11 finished"
"msg": "A:test_03 15-33-11 started"
"msg": "A:test_02 15-33-11 finished"
"msg": "A:test_09 15-33-12 finished"
"msg": "A:test_03 15-33-15 finished"
Results
Because of -f 3 Ansible started 3 hosts (1,9,6). Host 1 finished first and opened its slot to a new host that was waiting to start. Host 2 started. The same way host 3 started right after host 6 finished. Host 2, which started after host 9, finished before host 9.
i'm trying to write an ansible playbook to check if a set of machines are up and running.
Let's say, I've 5 machines to test. I'm trying to understand if I can have a playbook to capture status(up or down) of all 5 machines by checking one by one sequentially without failing the play if one of the machine is down.
It's possible to use wait_for_connection in the block. For example
- hosts: all
gather_facts: false
tasks:
- block:
- wait_for_connection:
sleep: 1
timeout: 10
rescue:
- debug:
msg: "{{ inventory_hostname }} not connected. End of host."
- meta: clear_host_errors
- meta: end_host
- debug:
msg: "{{ inventory_hostname }} is running"
- setup:
we have running 100 Machines in aws with tag Name=ad_server
so how can i run release code only 50% machines.
Example:
- hosts: tag_Name_ad_server
sudo: yes
remote_user: ubuntu
tasks:
- name: whatever
so how can i do this..
Option 1: serial + pause
This will use standard feature of batches for rolling updates and require some user interaction.
We add pause with prompt as a first task to wait for ENTER to be pressed at the start of every batch.
So press ENTER on the first 50%-batch and then abort execution when asked to start the second half.
- hosts: tag_Name_ad_server
user: ubuntu
serial: "50%"
tasks:
- pause: prompt="Press ENTER to run this batch"
- shell: echo task1
- shell: echo task2
With every playbook run serial will always choose the same servers from inventory. In this case first 50% from the list.
Option 2: form a new dynamic group
Loop through hosts in tag_Name_ad_server group and form a new 50_percent group.
Then execute your actual tasks within this new group.
No user interaction required.
- hosts: tag_Name_ad_server
gather_facts: no
tasks:
- group_by: key=50_percent
when: 100 | random > 50
- hosts: 50_percent
user: ubuntu
tasks:
- shell: echo task1
- shell: echo task2
With ever playbook run random will choose 50% random servers from the list.
Option 3: dirty trick with max_fail_percentage
If you have only one task to run, you can use max_fail_percentage: -1 to stop execution after first task of first batch.
This will make a 50%-batches, execute first task on every host of this batch and check failed servers count, as it always will be above -1 playbook will stop execution.
- hosts: tag_Name_ad_server
user: ubuntu
serial: "50%"
max_fail_percentage: -1
tasks:
- shell: echo task1
- shell: echo task2 # this task will never be executed with max_fail_percentage == -1
Folks,
I'd like to have a service be restarted individually on each host, and wait for user input before continuing onto the next host in the inventory.
Currently, if you have the following:
- name: Restart something
command: service foo restart
tags:
- foo
- name: wait
pause: prompt="Make sure org.foo.FooOverload exception is not present"
tags:
- foo
It will only prompt once, and not really have the effect desired.
What is the proper ansible syntax to wait for user input before running the restart task on each host?
Use a combination of serial attribute and step option of a playbook.
playbook.yml
- name: Do it
hosts: myhosts
serial: 1
tasks:
- shell: hostname
Call the playbook with --step option
ansible-playbook playbook.yml --step
You will be prompted for every host.
Perform task: shell hostname (y/n/c): y
Perform task: shell hostname (y/n/c): ****************************************
changed: [y.y.y.y]
Perform task: shell hostname (y/n/c): y
Perform task: shell hostname (y/n/c): ****************************************
changed: [z.z.z.z]
For more information: Start and Step
I went ahead with this:
- name: Restart Datastax Agent
tags:
- agent
hosts: cassandra
sudo: yes
serial: 1
gather_facts: yes
tasks:
- name: Pause
pause: prompt="Hit RETURN to restart datastax agent on {{ inventory_hostname }}"
- name: Restarting Datastax Agent on {{ inventory_hostname }}
service: name=datastax-agent state=restarted