<blockquote>
<p>Order of execution is important Server (Task A) needs to run before the client (Task B)</p>
</blockquote>
<p>Then why are your running Task A async in that case ? Is it just because <code>iperf --server</code> is not falling in the background and dying as soon as the shell task finishes ? A quick look at the <a href="https://iperf.fr/iperf-doc.php#3doc" rel="nofollow noreferrer">documentation</a> shows we can probably work around that problem with something like:</p>
<pre class="lang-bash prettyprint-override"><code>iperf3 --server --daemon --pidfile /path/to/iperf3.pid --logfile /path/to/log
</code></pre>
<p>Notes:</p>
<ul>
<li>I added the <code>logfile</code> option since I guess it can be useful but it is not mandatory for the current issue</li>
<li>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 <a href="https://iperf.fr/iperf-doc.php#service" rel="nofollow noreferrer">Running as a service on windows</a></li>
</ul>
<p>From what I understand the last unsolved issue is running the client tasks sequentially on each client host. This can be done using the <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html#rolling-update-batch-size" rel="nofollow noreferrer"><code>serial</code> keyword</a> on your play.</p>
<p>Here is an untested pseudo ansible setup summarizing what I understand from your requirements. Adapt to your real use-case.</p>
<p><strong><code>inventory/iperf_hosts.yml</code></strong></p>
<pre class="lang-yaml prettyprint-override"><code>---
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:
</code></pre>
<p><strong><code>playbook.yml</code></strong></p>
<pre class="lang-yaml prettyprint-override"><code>---
- name: Start the iperf server
  hosts: iperf_servers
  
  tasks:
    - name: Fire the start command
      command: &quot;iperf3 --server --daemon --pidfile {{ iperf_pid_file }} --logfile {{ iperf_log_file }}&quot;

- name: Launch clients one after the other.
  hosts: iperf_clients
  serial: 1
  
  tasks:
    - name: Run iperf3 client
      win_command: &quot;iperf3 -c {{ hostvars[group['iperf_servers'][0]].inventory_hostname }} -t {{ iperf_time }}&quot;
      args:
        chdir: &quot;{{ iperf_dest }}&quot;
      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: &quot;{{ iperf_pid_file }}&quot;
      register: slurped_pid

    - name: kill the iperf3 process
      command: &quot;kill {{ slurped_pid.content | b64decode }}&quot;
</code></pre>

CC BY-SA 4.0
2021-03-28T23:49:46.087Z
2021-04-08T07:15:11.200Z
2021-04-08T07:15:11.200Z
Zeitounator
<p>I'm trying to run two simple tasks</p>
<p><code>Task A</code> starts an Ipref3 server and waits for a client to connect<br />
<code>Task B</code> starts to run from <em>host-1</em> until the given timeout</p>
<p>once <code>Task B (host-1)</code> is over another <code>Task B</code> run from host-2</p>
<p><code>Task B</code> starts to run from <em>host-2</em> until the given timeout</p>
<p>What is a good approach to orchestrating this use-case?</p>
<p><strong>This is what I tried</strong></p>
<p><code>Task B</code> runs the client from multiple hosts (host-1, host-2, ..)</p>
<pre><code>- name: Run iperf3 client
  win_command: iperf3 -c {{ iperf_server }} -t {{ iperf_time }} 
  args:
    chdir: &quot;{{ iperf_dest }}&quot;
  register: iperf3_out

- debug:
    var: iperf3_out.stdout
</code></pre>
<p><code>Task A</code> run the server</p>
<pre><code>- name: Start iperf3 server
  shell: iperf3 --server
  async: &quot;{{ iperf_async }}&quot; # iperf_async = iperf_time + 10
  poll: &quot;{{ iperf_poll }}&quot;   # iperf_poll  = 0  
</code></pre>
<p>Is there a way to know when to confirm <code>Task A</code> is finished before I move to the next task.</p>
<p>NOTE: Order of execution is important Server (<code>Task A</code>) needs to run before the client (<code>Task B</code>)</p>

<ansible><automation>
Problem with Ansible Asynchronous actions
Hanoch
# Problem with Ansible Asynchronous actions

(Asked by: username_0 on 2021-03-15)

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)

**Tags:** ansible, automation


---

## 1 answers

### Answer by username_1 on 2021-03-28. Score: 1 | Accepted answer

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 }}"


---

