HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Problem with Ansible Asynchronous actions

Submitted by: @import:stackexchange-devops··
0
Viewed 0 times
problemactionswithasynchronousansible

Problem

I'm trying to run two simple tasks

Task A starts an Ipref3 server and waits for a client to connect

Task B starts to run from host-1 until the given timeout

once Task B (host-1) is over another Task B run from host-2

Task B starts to run from host-2 until the given timeout

What is a good approach to orchestrating this use-case?

This is what I tried

Task B runs the client from multiple hosts (host-1, host-2, ..)

- name: Run iperf3 client
  win_command: iperf3 -c {{ iperf_server }} -t {{ iperf_time }} 
  args:
    chdir: "{{ iperf_dest }}"
  register: iperf3_out

- debug:
    var: iperf3_out.stdout


Task A run the server

- name: Start iperf3 server
  shell: iperf3 --server
  async: "{{ iperf_async }}" # iperf_async = iperf_time + 10
  poll: "{{ iperf_poll }}"   # iperf_poll  = 0


Is there a way to know when to confirm Task A is finished before I move to the next task.

NOTE: Order of execution is important Server (Task A) needs to run before the client (Task B)

Solution

Order of execution is important Server (Task A) needs to run before the client (Task B)

Then why are your running Task A async in that case ? Is it just because iperf --server is not falling in the background and dying as soon as the shell task finishes ? A quick look at the documentation shows we can probably work around that problem with something like:
iperf3 --server --daemon --pidfile /path/to/iperf3.pid --logfile /path/to/log


Notes:

  • I added the logfile option since I guess it can be useful but it is not mandatory for the current issue



  • I took for granted you are running the server on a linux platform. Running it on Windows would apparently slightly change the below scenario. See Running as a service on windows



From what I understand the last unsolved issue is running the client tasks sequentially on each client host. This can be done using the serial keyword on your play.

Here is an untested pseudo ansible setup summarizing what I understand from your requirements. Adapt to your real use-case.

inventory/iperf_hosts.yml
---
iperf_servers:
vars:
iperf_pid_file: /tmp/iperf.pid
iperf_log_file: /tmp/iperf.log
hosts:
server1.local:
iperf_clients:
vars:
iperf_time: 1
iperf_dest: some\win\directory
hosts:
host1.local:
host2.local:
host3.local:


playbook.yml
---
  • name: Start the iperf server


hosts: iperf_servers

tasks:
- name: Fire the start command
command: "iperf3 --server --daemon --pidfile {{ iperf_pid_file }} --logfile {{ iperf_log_file }}"

  • name: Launch clients one after the other.


hosts: iperf_clients
serial: 1

tasks:
- name: Run iperf3 client
win_command: "iperf3 -c {{ hostvars[group['iperf_servers'][0]].inventory_hostname }} -t {{ iperf_time }}"
args:
chdir: "{{ iperf_dest }}"
register: iperf3_out

- debug:
var: iperf3_out.stdout

  • name: Now we are over with clients, kill the server


hosts: iperf_servers
# We already gathered facts at first play so we disable here
# You might want to disable in all other plays if you don't need facts at all
gather_facts: false

tasks:
- name: Slurp pid from file
slurp:
path: "{{ iperf_pid_file }}"
register: slurped_pid

- name: kill the iperf3 process
command: "kill {{ slurped_pid.content | b64decode }}"

Context

StackExchange DevOps Q#13549, answer score: 1

Revisions (0)

No revisions yet.